Кодуйте ціле число


33

Дано додатне ціле число n > 2. Перетворюємо його в масив наступним чином:

  1. Якщо вона дорівнює, 2повернути порожній масив
  2. В іншому випадку створіть масив усіх nпростих факторів, відсортованих за зростанням, потім кожен елемент замініть його індексом у послідовності простих чисел і, нарешті, перетворіть кожен елемент у масив

Наприклад, давайте перетворимо число 46в масив. По-перше, перетворіть його у масив основних факторів:

[2, 23]

Число 23є 9е простим, тому замінити 2з порожнім масивом і 23з [9]. Тепер масив стає:

[[], [9]]

Основними факторами 9є 3і 3, таким чином:

[[], [3, 3]]

Зробіть те саме для обох 3:

[[], [[2], [2]]]

І, нарешті:

[[], [[[]], [[]]]]

Тепер, щоб кодувати його, ми просто замінюємо кожну відкриту дужку на 1та кожну закриваючу дужку 0, потім видаляємо всі кінцеві нулі і опускаємо одну 1з кінця. Це наше двійкове число. Використовуючи наведений вище приклад:

[ ] [ [ [ ] ] [ [ ] ] ]

| | | | | | | | | | | |
| | | | | | | | | | | |
V V V V V V V V V V V V

1 0 1 1 1 0 0 1 1 0 0 0

Тепер просто опустіть останні три нулі та останню 1. Число стає числом, 10111001яке знаходиться 185в десяткових. Це очікуваний вихід. Зауважте, що до масиву до двійкових дужок перетворення основного масиву не включено.

Вхідні дані

Позитивне ціле число nбільше, ніж 2.

Вихідні дані

Зашифроване ціле число n.

Правила та формат IO

  • Діють стандартні правила.
  • Вхід може бути рядок або число (але у випадку рядка він повинен бути в базі 10).
  • Вихід може бути рядок або число (але у випадку рядка він повинен бути в базі 10).
  • Це , найкоротша відповідь у байтах виграє!

Тестові справи

Більше тестових випадків за запитом.

3 ---> 1
4 ---> 2
5 ---> 3
6 ---> 5
7 ---> 6
8 ---> 10
9 ---> 25
10 ---> 11
10000 ---> 179189987
10001 ---> 944359
10002 ---> 183722
10003 ---> 216499
10004 ---> 2863321
10005 ---> 27030299
10006 ---> 93754
10007 ---> 223005
10008 ---> 1402478

Пісочниця


Вам слід видалити тестовий випадок, 2оскільки для його роботи не потрібні матеріали.
Містер Xcoder

4
Мови видобутку, які не мають основних вбудованих модулів.
Містер Xcoder

3
@Paul. "[...] створити масив усіх основних факторів n, відсортованих за зростанням"

1
@Quelklef. Я працював над впровадженням ATP (просто для розваги, нічого серйозного) і намагався якось представляти кожне число за допомогою вкладених масивів. Отже, це кодування - перша ідея, яку я придумав.

1
@WheatWizard. Я не маю на увазі точного математичного сенсу слова ціле число . Я збираюся залишити його. :-)

Відповіді:


12

Хеск , 35 31 30 29 26 25 24 22 20 19 15 байт

-7 байт завдяки @Zgarb!

Збережено додаткові 4 байти, опосередковано, завдяки Zgarb

ḋhΣhgφṁȯ`Jḋ2⁰ṗp

Спробуйте в Інтернеті!

Пояснення

     φ             -- Define a recursive function which calls itself ⁰ and is applied to an Integer
      ṁ       p    -- map then concatenate over its prime factors
             ṗ     --   return their indices into the primes
            ⁰      --   and then recur, applying ⁰ to that number
       ȯ`Jḋ2       --   then surround it between the list [1,0] (binary 2)
    g              -- group adjacent equal elements
   h               -- drop last element (trailing 0s)
  Σ                -- concatenate
 h                 -- drop the last element
ḋ                  -- interpret as base 2

Я думаю, що це повинно працювати на 27 байт, але TIO вичерпується під час виводу типу ...
Zgarb

2
Неважливо, 25 байт і працює. Нарешті, випадок використання для φлямбда-фіксатора!
Згарб

Нічого, я ніколи не розумів випадків його використання, до цих пір
H.PWiz

Ми додали лямбдас на фіксацію Husk дуже рано, до того, як були запроваджені багатолінійні програми. Я думаю, ми думали, що це буде найкращий спосіб впоратися з рекурсією. Але вони досить незрозумілі, крім збереження одного байта в особливих випадках.
Згарб

`:0:1може бути `Jḋ2.
Згарб

7

Желе ,  22 20  19 байт

-1 спасибі Еріку Переможця (нульові хвости з обох сторін t, а не з правого боку œr)

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ

Монадична посилання, що приймає ціле число більше 2 і повертає ціле число більше 0 (2 також повертає 0 відповідно до оригінальної специфікації).

Спробуйте в Інтернеті!

Як?

Це майже точно повторює наведений опис, просто з деякими порядковими маніпуляціями для створення бінарного масиву ...

ÆfÆC$ÐLŒṘO%3ḟ2Ḋt0ṖḄ - Link: number n (>=2)
     ÐL             - loop until no more changes occur:
    $               -   last two links as a monad:
Æf                  -     prime factorisation (includes duplicates & vectorises)
  ÆC                -     count primes less than or equal (vectorises)
                    -   ...note for entries of 2 this yields [1]
                    -      then for entries of 1 it yields [], as required
       ŒṘ           - get a Python representation - just like in the OP,
                    -    something like: "[[], [[[]], [[]]]]" (for an input of 46)
         O          - convert to ordinals e.g. [91,91,93,44,32,91,91,91,93,93,44,32,91,91,93,93,93,93]
          %3        - modulo by 3         e.g. [ 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 2, 2, 1, 1, 0, 0, 0, 0]
            ḟ2      - filter discard twos e.g. [ 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
              Ḋ     - dequeue             e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0]
               t0   - strip zeros         e.g. [ 1, 0, 1, 1, 1, 0, 0, 1, 1]
                 Ṗ  - pop                 e.g. [ 1, 0, 1, 1, 1, 0, 0, 1]
                  Ḅ - binary to decimal   e.g. 185

Ага, так, я точно можу; Спасибі.
Джонатан Аллан

6

Python 2 , 212 177 байт

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;P=q=1;exec"P*=q*q;q+=1;"*~-j;i+=P%q
  while n%j<1:yield i;n/=j

Спробуйте в Інтернеті!

Відсутність простих вбудованих дійсно шкодить підрахунку байтів, і це час у TIO збільшується з більшими праймерами. Використання XNOR «s перевірка простоти.


Python 2 + gmpy2 , 175 байт

lambda n:int(g(n).rstrip("0")[1:-1],2)
g=lambda n:"1%s0"%"".join(map(g,p(n)))
def p(n,i=0,j=1):
 while n>1:
  j+=1;i+=is_prime(j)
  while n%j<1:yield i;n/=j
from gmpy2 import*

Спробуйте в Інтернеті!

Ця версія не вичерпується на більш великих тестових випадках (тобто 10000 - 10008).


5

Математика, 125 119 байт

Flatten[#//.{{1}->{1,0},a_/;a>1:>{1,List/@PrimePi[Join@@Table@@@FactorInteger@a],0}}]/.{1,d__,1,0..}:>{d}~FromDigits~2&

Використовує дещо інший підхід; перетворює прості індекси в {1, index, 0}та 2 до{1, 0} .

Спробуйте його на Wolfram Sandbox

Використання:

f = Flatten[ ...

f[10008]

1402478


Оригінальна відповідь працює на 10008, але ця не вдається
Келлі Лоудер

1
Виправлено @KellyLowder!
JungHwan Min


2

J, 74 73 66 байт

3 :'#.(}.~ >:@i.&1)&.|.2+}.;<@(_2,~_1,[:>:[:_1&p:q:) ::<"0@;^:_ y'

Спробуйте в Інтернеті!

Це справжній безлад, який, безумовно, потребує подальшого гольфу (наприклад, видалення явного визначення функції). Я думаю, що бокс, яким я займався, є особливо те, що піднімає обмін рахунку, оскільки я дійсно не знаю, що я там роблю (це було багато спроб і помилок). Крім того, я майже впевнений, що є якісь вбудовані, про які я забуваю (наприклад, мені це здається_2,~_1, ймовірно, є вбудований).

Пояснення (невольф)

Преамбула

Сидіти сильно, бо це не буде коротким поясненням. За іронією долі, лайливу мову поєднали з людиною-багатослівою.

Я розділю це на кілька функцій

encode  =. 3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::<"0@;^:_ y'
convert =. 3 : '2 + }. ; y'
drop    =. (}.~ >:@i.&1)&.|.
decode  =. #.
  • encode кодує ціле число, використовуючи _1 і _2 замість [і]
  • convert перетворює список _1 та _2 у список 1 та 0
  • drop краплі останніх 1 і кінцеві нулі
  • decode перетворює з двійкового списку в число

Я буду проходити вибірковий виклик за 46, який виражається у форматі без вогню

   decode drop convert encode 46
185

Кодування

Тут можна багато пояснити.

3 : '<@(_2,~_1, [: >: [: _1&p: q:) ::< "0@;^:_ y'
                                           ^:_      Do until result converges
                                          ;          Raze (remove all boxing)
                                       "0            For each
                               q:                     Factorize
                         _1&p:                        Get index of prime
                   >:                                 Add 1 (J zero-indexes)
            _1,                                       Prepend -1
        _2,~                                          Append -2
     <                                                Box resulting array
                                   ::                If there is an error
                                     <                Box the element

Зауважте, що чітке визначення функції 3 : '[function]'оцінює функцію так, ніби вона була на REPL правильним аргументом, що замінює кожен екземпляр y(це означає, що я можу уникнути необхідності використання caps ( [:), atops ( @) та ats ( ) @:ціною кілька байт).

Ось як виглядає кожна наступна ітерація на вході 46

┌─────────┐    ┌──┬─────┬─────────┬──┐    ┌──┬──┬──┬──┬───────┬───────┬──┬──┐
│_1 1 9 _2│ => │_1│_1 _2│_1 2 2 _2│_2│ => │_1│_1│_2│_1│_1 1 _2│_1 1 _2│_2│_2│ =>
└─────────┘    └──┴─────┴─────────┴──┘    └──┴──┴──┴──┴───────┴───────┴──┴──┘

┌──┬──┬──┬──┬──┬─────┬──┬──┬─────┬──┬──┬──┐    
│_1│_1│_2│_1│_1│_1 _2│_2│_1│_1 _2│_2│_2│_2│ => the final iteration is just every
└──┴──┴──┴──┴──┴─────┴──┴──┴─────┴──┴──┴──┘    value in its own box

Ця функція використовує несприятливий ( ::) з метою вкладення значень у "дужки" (тут використовуються дужки -1 та -2). В основному, кожен раз, коли ми розбиваємо на фактори і перетворюємо їх на індекси простих чисел, _1 є попередньою, а _2 додається, які виконують роль дужок. Коли функція викликається цими елементами, вона просто повертає їх як є, оскільки q:буде помилка при спробі факторизувати негативне число. Це також пощастило , що q:це НЕ помилка при спробі факторізовать 1 , а замість цього повертає порожній масив (за бажанням).

Перетворити

3 : '2 + }. ; y'
            ;     Raze (remove boxing)
         }.       Behead (remove head)
     2 +          Add 2

Перетворити набагато простіше. Він просто видаляє весь бокс, а також перший елемент, а потім перетворює все на 1 і 0 (просто додавши 2)

Крапля

(}.~ >:@i.&1)&.|.
             &.|.  Reverse, apply the left function, and then undo
 }.~ >:@i.&1        Drop the leading zeroes and first 1
        i.&1         Index of first one
     >:              Add 1
 }.~                 Drop

Це повертає список, знаходить перше, а потім скидає всі значення до цього, а потім повертає список знову.

Розшифруйте

Декодування - це вбудована функція, #.яка бере список 1s і 0s і перетворює його у двійкове число.


2

Сітківка , 244 227 225 байт

+%(G`
\d+
$*0¶$&$*
+`^00(0+)
0$1¶$0
A`^(00+?)\1+$
^0+
$0;1
+`(1+)¶0+(?=¶)
$0;1$1
+`¶(11+?)(\1)*$
¶$1¶1$#2$*1
1$

m`^11$
[]
m`^1+
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶
$1;$2$3$2¶
0+;1+¶

)`1+
$.0
T`[]¶`10_
10+$

1
01
+`10
011
^0+

1

Спробуйте в Інтернеті!

Це прямий підхід за алгоритмом, продемонстрованим у питанні. Генерація простих індексів - це експоненціальна складність, тому вона буде вичерпана для більшої кількості вхідних даних

Пояснення:

+%(G`                Repeatedly apply on each line:
\d+                      If the line is a number, convert it to unary 0s and 1s
$*0¶$&$*
+`^00(0+)                Generate all prefixes of the zeros greater than 1
0$1¶$0
A`^(00+?)\1+$            Remove non-prime strings of zeros
^0+                      Index the first zero set (00) as 1
$0;1
+`(1+)¶0+(?=¶)           Index the rest of the zeroes as their prime index
$0;1$1
+`¶(11+?)(\1)*$          Compute prime factors of input value
¶$1¶1$#2$*1
1$                       Remove the 1 factor (not really prime)

m`^11$                   Turn all 2 prime factors to []
[]
m`^1+                    Surround all non-2 prime factors in brackets
[¶$.0$*0¶]
+s`(0+);(1+)(.+¶)\1¶     Convert non-2 prime factors to their index
$1;$2$3$2¶
0+;1+¶                   Remove the list of primes

)`1+                     Return all primes back to decimal ready to be repeated
$.0
T`[]¶`10_            Then convert all [ to 1 and ] to 0, and remove linefeeds
10+$                 Remove the final 1 and trailing zeroes

1                    Convert from binary to unary
01
+`10
011
^0+

1                    Convert from unary to decimal

1

Haskell , 162 160 155 байт

sum.zipWith((*).(2^))[0..].tail.snd.span(<1).(r%)
r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]
_%1=[]
((i,q):p)%n|mod n q<1=r%div n q++0:r%i++[1]|1<3=p%n

Спробуйте в Інтернеті!

Пояснення:

r=zip[1..][x|x<-[2..],all((>0).mod x)[2..x-1]]визначає нескінченний список кортежів простих чисел і їх індексів: [(1,2),(2,3),(3,5),(4,7),(5,11),(6,13), ...].

Функція (%)приймає цей список rі число nі перетворює число в реверсивне представлення масиву факторів. Це робиться шляхом кроку до rтих пір, поки ми не знайдемо просте, що розділяє n. Потім ми рекурсивно визначити уявлення індексу цього простого і укласти його в 0і 1й випереджати уявлення nділиться цим штрихом.

Бо n=46це дає список, [0,0,0,1,1,0,0,1,1,1,0,1]з якого потім провідні нулі ( snd.span(<1)) та наступні 1(tail випадають ). Потім список перетвориться в десяткове число з допомогою поелементного множення з переліком повноважень два і підсумовування отриманого списку: sum.zipWith((*).(2^))[0..].


0

JavaScript, 289 байт

Байти - це сума коду JavaScript без розривів рядків після коми (які вставляються лише для кращого форматування та читабельності) (256 байт) та додаткових символів для перемикання командного рядка, необхідного при використанні Chrome (33 байти).

'use strict'
var f=(n,i=2,r=[])=>n>1?n%i?f(n,i+1,r):f(n/i,i,r.concat(i)):r,
c=(p,r=1,i=2)=>i<p?f(i)[1]?c(p,r,i+1):c(p,r+1,i+1):r-1?f(r).map(h):[],
h=a=>c(a),
s=a=>a.reduce((r,e)=>r+s(e),'1')+' ',
o=i=>+('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1))

І довша, краще читаемая версія:

'use strict';
const f = (n,i=2,r=[]) => n>1 ? n%i ? f(n,i+1,r) : f(n/i,i,r.concat(i)) : r;
const c = (p,r=1,i=2) => i<p ? f(i)[1] ? c(p,r,i+1) : c(p,r+1,i+1) : r-1 ? f(r).map(h) : [];
const h = i => c(i);
const s = a => a.reduce((r,e) => r+s(e),'1')+' ';
const o = i => +('0b'+s(f(i).map(h)).trim().replace(/ /g,'0').slice(1,-1));

Деякі короткі пояснення:

f є суто функціональним алгоритмом факторизації хвостово-рекурсивної факторизації.

cпідраховує, на якому місці rпросте число pвиникає в послідовності простих чисел і повертає або [](якщо p=2і r=1), або розподіляє фактори та подальші процесиr за допомогою рекурсії.

hце невелика допоміжна функція, яка, на жаль, необхідна, як mapвикликає надану функцію, numberOfCurrentElementяк другий і wholeArrayяк третій аргумент, таким чином, переосмислюючи значення за замовчуванням, надані в тому cвипадку, якщо ми передамо цю функцію безпосередньо (мені знадобилося деякий час, щоб дістатись після цієї нерівності; замінаh за його визначенням буде на кілька байт довше).

sперетворює згенерований масив у рядок. Ми використовуємо blankзамість того , 0щоб ми могли використовувати trim()вo .

o - це функція, яку потрібно викликати зі вхідним значенням i яке повертає вихід. Він генерує бінарне подання рядків, необхідне специфікації, і перетворює його в (десяткове) число.

Редагувати: Chrome потрібно запускати, chrome --js-flags="--harmony-tailcalls"щоб увімкнути оптимізацію хвостової рекурсії (див Https://v8project.blogspot.de/2016/04/es6-es7-and-beyond.html ). Це також вимагає використання суворого режиму.

Наступний тест показує, що обчислення для деяких значень трохи повільні (найдовший 10007на моєму комп’ютері - більше шести секунд ). Цікаво, що без оптимізації хвостової рекурсії обчислення проходять набагато швидше (приблизно коефіцієнт 5), коли немає переповнення стека.

for (let i=3; i<=10008; i==10 ? i=10000 : ++i) {
    let time = new Date().getTime();
    let val = o(i);
    time = new Date().getTime() - time;
    document.write(i + ': ' + o(i) + ' (computed in ' + time + ' ms)<br>');
}

0

тинілісп , 209 байт

(load library
(d [(q((N)(map(q((P)([(length(filter prime?(1to P))))))(reverse(prime-factors N
(d B(q((L)(c 1(insert-end 0(foldl concat(map B L
(d T(q((N)(if(mod N 2)(/ N 2)(T(/ N 2
(q((N)(T(from-base 2(t(B([ N

Останній рядок - це неназвана функція, яка обчислює вказане кодування. Спробуйте в Інтернеті!

Попередня гольф-версія

Це код, який я мав ще до того, як почав займатися гольфом:

(load library)

(def prime-index
 (lambda (P)
  (length (filter prime? (1to P)))))

(def to-list
 (lambda (N)
  (map to-list
   (map prime-index
    (reverse (prime-factors N))))))

(def to-bits
 (lambda (L)
  (cons 1
   (insert-end 0
    (foldl concat
     (map to-bits L))))))

(def trim
 (lambda (N)
  (if (mod N 2)
   (div2 N 2)
   (trim (div2 N 2)))))

(def encode
 (lambda (N)
  (trim
   (from-base 2
    (tail (to-bits (to-list N)))))))

0

05AB1E , 18 байт

ΔÒ.Ø>}¸»Ç3%2K0ܨ2β

Спробуйте в Інтернеті!

Пояснення:

Δ    }       # loop until a fixed point
 Ò           # replace each number with its prime factorization
  .Ø>        # replace each prime with its 1-based index
¸»           # after the loop: join to a string
  Ç          # get ASCII value of each character
   3%        # modulo 3 (maps '[' to 1, ']' to 0, ' ' to 2, ',' to 2)
     2K      # remove 2s
       0Ü    # trim trailing 0s
         ¨   # remove the last 1
          2β # parse as base 2
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.