Обчисліть послідовність Колакоскі


54

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

Послідовність Kolakoski - це весела самореференційна послідовність, яка має честь бути OEIS послідовністю A000002 (і це набагато простіше зрозуміти та реалізувати, ніж A000001). Послідовність починається з 1 , складається лише з 1 s і 2 s, а елемент послідовності a (n) описує довжину n- го запуску 1 s або 2 s у послідовності. Це однозначно визначає послідовність, яка повинна бути (з візуалізацією прогонів під нею):

1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1,2,1,1,2,1,2,2,1,1,2,1,1,2,...
= === === = = === = === === = === === = = === = = === === = === =
1, 2,  2, 1,1, 2, 1, 2,  2, 1, 2,  2, 1,1, 2, 1,1, 2,  2, 1, 2, 1,...

Ваше завдання, звичайно, реалізувати цю послідовність. Ви можете вибрати один з трьох форматів для цього:

  1. Візьміть вхід n і виведіть n- й член послідовності, де n починається або з 0, або з 1 .
  2. Візьме вхід н і вихід терміни аж до і включаючи в п - го члена послідовності, де п починається або від 0 або 1 (тобто або роздрукувати перший п або перший п + 1 Терміни).
  3. Виводити значення з послідовності на невизначений термін.

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

У третьому випадку, якщо ваше подання є функцією, ви також можете повернути нескінченний список або генератор мовами, які їх підтримують.

Ви можете написати програму чи функцію та скористатися будь-яким із наших стандартних методів отримання вводу та надання виводу. Зауважте, що ці лазівки за замовчуванням заборонені.

Це , тому найкоротший вірний відповідь - вимірюється в байтах - виграє.



Узагальнення проблеми , але можливі оптимізації, оскільки фіксована початкова частина послідовності.
Джузеппе

Відповіді:


17

Желе , 7 байт

2Rṁxṁµ¡

Це повна програма, яка друкує перші n термінів.

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

Як це працює

2Rṁxṁµ¡  Main link. Argument: n (integer)

     µ   Combine the preceding links into a monadic chain.
      ¡  Set t = n.  Call the chain n times, updating t with the return value after
         each call. Yield the last value of t.
2R           Set the return value to 2 and take its range. Yields [1, 2].
  ṁ          Mold; cyclically repeat 1 and 2 to match t's length.
             In the first run, ṁ promotes t = n to [1, ..., n].
   x         Repeat the k-th element of the result t[k] times.
             In the first run, x repeats each element t = n times.
    ṁ        Mold; truncate the result to match the length of t.
             In the first run, ṁ promotes t = n to [1, ..., n].                 

Приклад виконання

Нехай n = 5 .

Перший виклик ланцюга повторюється 1, 2 циклічно, щоб досягти довжини 5 , потім кожен елемент у 5 разів і, нарешті, обрізає результат на довжину 5 .

  1         2         1         2         1
x 5         5         5         5         5
---------------------------------------------------
  1 1 1 1 1 2 2 2 2 2 1 1 1 1 1 2 2 2 2 2 1 1 1 1 1

  1 1 1 1 1

Це дає список довжиною 5 . Перший елемент - це перший елемент послідовності Колакоскі.

Другий виклик ланцюга повторюється циклічно 1, 2, щоб досягти довжини 5 , потім повторює k- й елемент j разів, де j - k- й елемент попереднього списку, і, нарешті, обрізає результат на довжину 5 .

   1 2 1 2 1
x  1 1 1 1 1
------------
   1 2 1 2 1

   1 2 1 2 1

Це дає ще один список довжиною 5 . Перші два елементи - це перші два елементи послідовності Колакоскі.

Процес триває ще три повторення.

   1 2   1 2   1
x  1 2   1 2   1
----------------
   1 2 2 1 2 2 1

   1 2 2 1 2
   1 2   1   2 1
x  1 2   2   1 2
------------------
   1 2 2 1 1 2 1 1

   1 2 2 1 1
   1 2   1   2 1
x  1 2   2   1 1
----------------
   1 2 2 1 1 2 1

   1 2 2 1 1

Це перші п’ять елементів послідовності Колакоскі.


12

Python 2 , 51 байт

l=[2]
print 1,2,
for x in l:print x,;l+=x*[l[-1]^3]

Друкує нескінченно. Створює список lпід час його перегляду. Для кожного запису xз l, додає xкопії 1або 2, в залежності від того знаходиться навпроти поточного останнього елемента.

Основна складність - це вирішення початкового фрагмента самореференції [1,2,2]. Цей код просто виводить початковий 1,2і надходить звідти. Додатковий друк коштує 12 байт. Без цього:

39 байт , відсутні перші два записи:

l=[2]
for x in l:print x;l+=x*[l[-1]^3]

Ще один підхід - спеціально ініціалізувати перші два записи. Ми инициализируем , lяк [0,0,2]так , що перші два записи не викликають додавання, але print x or nробить їх надрукувати як n.

51 байт

l=[0,0,2]
n=1
for x in l:print x or n;l+=x*[n];n^=3

Ще одне виправлення - ініціалізувати l=[1], відстежувати чергування вручну nта виправляти друк:

51 байт

n,=l=[1]
for x in l:print(l==[1,1])+x;l+=x*[n];n^=3

Без цього (l==[1,1])+все працює, крім надрукованих послідовностей, 1,1,2а не починається 1,2,2. Має бути кращий спосіб визнати, що ми на цьому другому кроці.

І ще одне дивне виправлення, якесь те саме число байтів:

51 байт

l=[1];q=2
for x in l:print x;l+=x*[l[-1]^3]*q;q=q<2

12

Wumpus , 13 11 байт

=[=)O?=!00.

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

Друкує послідовність необмежено без роздільників.

Я щиро здивований тим, наскільки це коротко.

Пояснення

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

     The entire program is run in a loop.
     At the beginning of loop iteration i, a(i)-1 will be at the bottom of the
     stack and the first element of the ith run of values will be on top.
     The caveat is that on the first iteration, the stack is empty, but
     popping from an empty stack produces an implicit zero.
=    Duplicate the top of the stack. Since this is defined as "pop x, push
     x, push x" this will result in 2 zeros when the stack is empty.
     After this we've got two copies of the ith run's value on top of the stack.
[    Pull up a(i)-1 from the bottom of the stack.
=)O  Duplicate, increment to a(i) and print it.
?=   If a(i)-1 is 1 (as opposed to 0), make another copy of the top of the
     stack. We've now got a(i)+1 copies, so one more than the run should be 
     long, but that's great because we can use the additional copy to get 
     the start of the next run.
!    Logical negation which swaps 0 and 1.
00.  Jump back to the beginning of the program.

10

Брахілог , 30 26 25 23 17 16 14 байт

~a₀{1|2}ᵐḅlᵐ?l

Виводить перші n значень. Використовує "змінну виводу" .для введення та виводить на "вхідну змінну" ?. Спробуйте в Інтернеті!

Пояснення

Я дуже задоволений тим, наскільки це виявилося декларативно: програма - це в основному опис списку результатів на високому рівні та його відношення до вхідних даних.

~a₀{1|2}ᵐḅlᵐ?l  Input is a number N.
                Output is a term that I'll call T.
~a₀             T is a prefix of a list L.
   {   }ᵐ       Each element of L
    1|2         is either 1 or 2.
         ḅ      If you cut L into blocks of equal elements
          lᵐ    and take the length of each block,
            ?   the result is T.
             l  The length of T is N.

Оскільки {1|2}ᵐвипробовує списки в лексикографічному порядку, вихід розпочнеться з 1.


9

Лушпиння , 10 байт

Ṡωo↑⁰`Ṙ¢ḣ2

Повертає перші n значень. Спробуйте в Інтернеті!

Пояснення

Ṡωo↑⁰`Ṙ¢ḣ2  Input is an integer N.
        ḣ2  The range [1,2]
       ¢    Cycle: C = [1,2,1,2,1,2...
 ω          Iterate until fixed point is found:
Ṡ    `Ṙ      Replicate the list C element-wise according to the current list,
  o↑⁰        then take first N elements.

Для введення 20 процес йде так:

[1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2...
[1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2,2,1,2]
[1,2,2,1,1,2,1,1,2,2,1,2,2,1,1,2,1,1,2,2]
[1,2,2,1,1,2,1,2,2,1,2,1,1,2,2,1,2,2,1,1]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,1,2]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1]
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1,2,2,1]

1
Ось варіант друку послідовності на невизначений час, кількість байтів, але, можливо, ви побачите кілька можливостей для гольфу, яких я не пробував в Інтернеті!
Лев

9

Java 10, 155 108 105 100 97 байт

v->{var s="122";for(int i=1;;s+=(1+i%2)*(s.charAt(i)>49?11:1))System.out.print(s.charAt(++i-2));}

Друкує нескінченно без роздільника.

-3 байти після непрямої підказки від @Neil .
-5 байт завдяки @MartinEnder .
-3 байти перетворення Java 8 в Java 10.

Пояснення:

Спробуйте в режимі он-лайн (тайм-аут через 60 сек на TIO).

v->{              // Method with empty unused parameter and no return-type
  var s="122";    //  String, starting at "122"
  for(int i=1;;   //  Loop `i` from 1 upwards indefinitely
      s+=         //    After every iteration: Append the String with:
         (1+i%2)  //     1+`i`modulo-2
         *(s.charAt(i)>49?11:1))
                  //     either once or twice depending on the digit at index `i`
    System.out.print(s.charAt(++i-2));}
                  //   Print the character at index `i-2` of the String
                  //   After we've first increased `i` by 1 with `++i`

1
Мені подобається, як ти зробив такий вигляд таким простим.
Ерік Аутгольфер

@EriktheOutgolfer Дякую! :) Коли я прочитав виклик, я не був впевнений, як навіть почати, але потім мене вдарило (використовуючи список із початковим [1,2,2]і піти звідти), і я написав відповідь 155 байтів (яка тепер гольфується за допомогою String замість списку).
Кевін Круїссен

Чому б не використовувати (3-i)замість (1+i%2)?
Ерік Аутгольфер

1
@EriktheOutgolfer, оскільки iце не 1 або 2, це рядковий індекс.
Мартін Ендер

7

Желе , 10 байт

’߀+\<¹SḂ‘

Повертає n- й доданок.

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

Як це працює

’߀+\<¹SḂ‘  Main link. Argument: n (positive integer)

’           Decrement; yield n-1.
 ߀         Recursively map the main link over [1, ..., n-1].
   +\       Take the cumulative sum.
            The k-th sum is the combined length of the first k runs.
     <¹     Compare each sum with n.
       S    Sum the Booleans.
            This counts the number of runs that occur before the n-th term.
            If there's an even number (including 0) of runs, the n-th term is 1.
            If there's an odd number of runs, the n-th term is 2.
        Ḃ   Extract the least significant bit of the count.
         ‘  Increment.

7

Haskell , 33 байти

r=r%1
~(x:t)%n=n:[n|x>1]++t%(3-n)

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

Ørjan Johansen врятував 7 байт, використовуючи непереборний зразок для примушування префікса.


5
Ви можете зберегти 7 байт, зробивши його лазурнішим. Спробуйте в Інтернеті!
Ørjan Johansen

@ ØrjanJohansen Це дивовижно і лінивий малюнок для мене чарівний. Хочете опублікувати власну відповідь?
xnor

Ні, ти був там більшу частину шляху. Використовуючи n:на початку виразу, вам не потрібно знати, що xіснує для створення першого n. Але вам потрібно, щоб шаблон був ледачим, щоб уникнути перевірки його функцією перед тим, як дістатися до n:.
Шріхан Йохансен

6

Gol> <> , 8 7 байт

:{:PnKz

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

Пояснення

Це порт моєї відповіді Wumpus . Gol> <> в основному мова , який має всі необхідні функції для порту відповідь Wumpus ( в Зокрема, маються на увазі нулі в нижній частині стека, «дублюючі» реалізований «поп, поштовх, поштовх», і команда обертання стека), але :

  • Він має тороїдальну сітку, а це означає, що нам не потрібно явного 00.переходу до початку.
  • Він має K"pop N, потім повторює наступний елемент N разів", який може замінити ?=, зберегти ще один байт.

Отже, відображення від Wumpus до Gol> <> стає:

Wumpus   Gol><>
=        :
[        {
=        :
)        P
O        n
?=       K
!        z
00.

6

Мова програмування Шекспіра , 594 583 572 байт

Дякуємо Еду Вайну за -10 байт!

,.Ford,.Puck,.Act I:.Scene I:.[Enter Ford and Puck]Ford:You cat!Open heart!You big cat!Open heart!Puck:Remember you!Remember me!Scene V:.Ford:You is the sum ofI a cat!Puck:Recall!Open heart!Ford:Remember a pig!Is I nicer a cat?If notyou be the sum ofyou a big pig!Scene X:.Puck:Recall!Ford:Is I nicer zero?If soremember I!If solet usScene X!Puck:Is I nicer zero?You is the sum ofI a big cat!If soyou is I!Remember zero!Remember I!Remember you!You be the difference betweena big cat you!Scene L:.Ford:Recall!Is you worse I?If so,let usScene V!Puck:Remember I!Let usScene L!

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

Це гольф-версія нелігованого рішення Еда Вайна , починаючи з 828-байтного рішення, яке він зв'язав у коментарях, і піде звідти трохи горіхів.

Пояснення:

,.Ford,.Puck,.Act I:.Scene I:.[Enter Ford and Puck]    Boilerplate, introducing the characters
Ford:You cat!Open heart!You big cat!Open heart!  Print 1,2 as the first two terms of the sequence

Puck:Remember you!Remember me!  Initialise stack as 0, 2
                                Ford's value is currently 0, representing the value to be pushed to the stack

Scene V:.     Start infinite loop
  Ford:You is the sum ofI a cat!         
  Puck:Recall!Open heart!                 Pop the next value in the stack and print it
  Ford:Remember a pig!                    Push -1 as the end of the stack
  Is I nicer a cat?                       If Ford's value is 2
  If notyou be the sum ofyou a big pig! Subtract 2 from Puck's value to represent making 2 only one copy

        #Reverse the stack until it reaches the terminator value 0 or -1
  Scene X:.Puck:Recall!Ford:Is I nicer zero?If soremember I!If solet usScene X!

  Puck:Is I nicer zero?                          Check if the Puck's value is bigger than 0 (only making one copy)
  You is the sum of Ia big cat!                 Set Ford's value to Puck+2 to counter the change
  If soyou is I!                                But undo it if making one copies
  Remember zero!                                 Push 0 as the stack terminator
  Remember I!                                    Push Ford's value, which is 0 or -1 if this is a single copy, or 1 or 2 for a double copy
  Remember you!                                  Push one copy of Puck's value
  You be the difference betweena big cat you!   Map Ford's value from 1,2 to 1,0

  Scene L:.   #Reverse the stack until it reaches the terminator 0 
     Ford:Recall!Is you worse I?If solet us Scene V!
     Puck:Remember I!Let usScene L!

Приємно! Ви можете зберегти 7 байт, зробивши одиноку дитину замість близнюків (-1 або 0). Це коштує вам 1 байт безпосередньо перед сценою X (коли "Якщо так" стає "Якщо ні"), а інший байт - відразу після циклу Scene X (коли "Чи тобі краще", то стає "Чи я кращий нуль"). Економія полягає в тому, що ви можете замінити "Якщо ні, запам'ятайте вас!" просто "Запам’ятай мене!" на один рядок раніше. Вставляємо або другу дитину, або запасний термінатор. (Ось чому вам потрібно змінити тонко врівноважений "Чи я вам приємніший?" - Ви більше не можете розраховувати на Ford == 0 після сцени X.) Ось TIO, 587 байт: tinyurl.com/yb9zg4gp
Ed Wynn

Ви можете видалити перший "Якщо так" зі сцени L і перемістити команду до початку сцени V. Це заощадить вам лише 1 байт, тому що вам потрібен новий "Ford:". Але ви економите пару байтів у Сцені I, доки ви можете розраховувати на те, що Ford автоматично не буде ініціалізований. Ви не маєте права покладатися на це, але це може спрацювати: ось TIO, 584 байти: tinyurl.com/y9f6vy7u
Ed Wynn

5

> <> , 13 12 байт

0:{:1+n?:0=!

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

Порт відповіді Wumpus Мартіна Ендера . На жаль, в ній ><>немає інкременту чи команди інвертування, а також немає неявних 0 у нижній частині стека, тому це в кінцевому підсумку стає трохи довше.


1
Так, це я мав до того, як згадував Гола> <>. :)
Мартін Ендер

5

JavaScript, 67 66 60 58 52 51 50 байт

Ну, це змусило мого мозку свербіти більше, ніж це повинно бути! Повертає цей nтермін, 0-індексований.

s=`122`
x=1
f=n=>s[n]||f(n,s+=s[++x%2]*(s[x]+0-9))

5 + 1 байт збережено завдяки tsh, чухаючи сверблячий мозок!


Перевірте це

З наведеного нижче фрагмента буде виведено перші 50 термінів.


Пояснення

Це один з тих рідкісних випадків, коли ми можемо оголосити деякі змінні за межами нашої функції, змінити їх у межах функції та все ще мати можливість повторно використовувати їх при наступних викликах функції.

s=`122`       :Initialise variable s as the string "122"
x=1           :Initialise variable x as integer 1
f=n=>         :Named function f taking input as an argument through parameter n
 s[n]         :If s has a character at index n, return it and exit
 ||           :Or
 f(n          :Call f with n again
  ,s+=        :At the same time, append to s
  s[++x%2]    :  Increment x, modulo by 2 and get the character at that index in s
  *           :  Multiplied by (the above gets cast to an integer)
  (s[x]+0-9)  :  Append a 0 to the xth character of s and subtract 9
 )            :  (The above gives "1"+0-9="10"-9=1 or "2"+0-9="20"-9=11)

А як жеn=>(g=s=>s[n]||g(s+(++x%2+1)*(10*s[x]-9)))('122',x=1)
тш

Btw, чи s='122',x=1,g=n=>s[n]||g(n,s+=(++x%2+1)*(10*s[x]-9))вважається дійсним подання?
tsh

Спасибі, @tsh. s[n]||був ясний випадок не бачити деревини для дерев! Ваша друга пропозиція не буде дійсною, оскільки функцію можна було викликати лише один раз; s& xпотрібно ініціалізувати кожного виклику.
Кудлатий

другий робить багаторазового використання, до тих пір , як sі xне чіпали іншими кодами між кожним викликає (що за замовчуванням).
tsh

1
Приємно! s[x]+0-9досить акуратний трюк
JollyJoker

4

Пітон (2 і 3), 65 60 байт

f=lambda n:sum([f(i)*[i%2+1]for i in range(2,n)],[1,2,2])[n]

Повертає n- й запис, 0-індексований.

Альтернатива (65 байт):

f=lambda n:n>1and sum([f(i)*[i%2+1]for i in range(n)],[])[n]or-~n

3
Ласкаво просимо до PPCG!
Мартін Ендер

1
Ви можете (мабуть, я ще не тестував) зберегти 5 байт в альтернативній версії, використовуючи [1,2,2]в якості початкового значення вsum
Rod


4

мозковий ебать , 61 байт

+.+.[.[>]>+++>+++<<<[->+>->-<<<]<[[->+<]<]>>--[[>]<,<[<]>+]>]

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

Друкує числа як char-коди нескінченно. Для наочності ось версія, яка друкує цифрами (за винятком перших двох елементів, які досить просто перевірити).

Як це працює:

+.+. Prints the first two elements. These are the self-referential elements
     This also intitialises the tape with the third element, 2
[ Start infinite loop
   . Print current lowest element
   [>]>+++>+++ Move to end of tape and create two 3s
   <<<[->+>->-<<<] Subtract the last element of the tape from these 3s
   <[[->+<]<]>> Move to the beginning of the tape
   --  Subtract two from the first element
       This leaves 2 as 0 and 1 as -1
   [ If the number was 1
     [>]<,  Delete the excess element from the end of the tape
     <[<]>+ Remove the -1
   ]
   > Move to the next element of the list
]

4

05AB1E , 12 9 байт

Збережено 3 байти завдяки Grimy

Друкує перші n елементів.

Δ2LÞsÅΓI∍

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

Пояснення

Δ           # repeat until ToS doesn't change
 2LÞ        # push [1,2,1,2 ...]               
    sÅΓ     # run-length encode with previous value (initially input)
       I∍   # extend/shorten to the length specified by input

Розшифровка довжини пробігу тепер є вбудованою, тому це просто може бути 2L[2LÞsÅΓ.
Гримі

Або ще краще: ∞[2LÞsÅΓ.
Гримі

Або Δ2LÞsÅΓI∍для версії, яка друкує перші n елементів із заданим входом n.
Grimmy

@Grimy: Дякую! Мені подобається перша російська версія, оскільки вона фактично припиняється :)
Emigna

3

05AB1E , 15 байт

ƵLS[DNÌ©èF®É>¸«

Спробуйте в Інтернеті! або з обмеженням ітерації

Пояснення

ƵLS               # push our initial list [1,2,2]
   [              # for every N in [0 ...
    D             # duplicate current list of numbers
     NÌ©è         # get the N+2'th element from the list
         F        # that many times do
          ®É>     # push ((N+2)%2==1)+1
             ¸«   # append to current list

Замість того ¸«, =надрукує їх на 2 байта збережені. ƵLS[NÌ©èF®É>=, Не потрібно обманювати, якщо ви не споживаєте.
Чарівна восьминога Урна

@MagicOctopusUrn: Перші 3 статті я не створюю, тому друк, на жаль, не працює
Emigna


3

J , 12 байт

Функція з одним аргументом, що приймає n і виробляє перші n доданків. Спробуйте в Інтернеті!

$(1+2|I.)^:]

Якраз розплющую стару відповідь на старе запитання.

I.є дієсловом, яке бере масив чисел і виписує список індексів, так що якщо k -й елемент масиву n , то індекс k з'являється n разів. Ми будемо використовувати його для завантаження послідовності Kolakowski від початкового насіння. Кожен крок буде діяти наступним чином:

1 2   2   1 1 2   1 2   2   1   (some prefix)
0 1 1 2 2 3 4 5 5 6 7 7 8 8 9   (use I.)
0 1 1 0 0 1 0 1 1 0 1 1 0 0 1   (mod 2)
1 2 2 1 1 2 1 2 2 1 2 2 1 1 2   (add 1) 

Якщо ми виконуємо цю операцію ( 1+2|I.) знову і знову, починаючи з 10, це виглядає приблизно так:

10
1 1 1 1 1 1 1 1 1 1
1 2 1 2 1 2 1 2 1 2
1 2 2 1 2 2 1 2 2 1 2 2 1 2 2
1 2 2 1 1 2 1 1 2 2 1 2 2 1 1 ...
1 2 2 1 1 2 1 2 2 1 2 1 1 2 2 ...
1 2 2 1 1 2 1 2 2 1 2 2 1 1 2 ...

Зауважте, як ми з кожним разом отримуємо все більш правильні терміни, і через деякий час перші n термінів виправлені. Кількість ітерацій, необхідних для вирівнювання, важко точно описати, але вона виглядає приблизно n логарифмічною в n , тому, якщо ми просто виконаємо її n разів ( ^:]), це повинно бути добре. (Ознайомтеся з цими іншими послідовностями OEIS для отримання додаткової інформації: тривалість генерації , часткові суми .)

Як тільки ми це зробимо, все, що нам потрібно зробити, - це взяти перші n термінів, використовуючи $. Конструкція $vдля будь-якого дієслова vє прикладом гачка, і його надання nв якості аргументу буде виконано n $ (v n).

Ось старий 13-байтовий версія , яка є набагато менш марнотратно часу і простору: ($1+2|I.)^:_~. Він обрізає вхід на кожному кроці, тож ми можемо виконати рівно стільки разів, скільки потрібно, а не лінійно багато разів.


О, це прекрасно працює з I.. Мені завжди хотілося побачити функцію копіювання, яку він використовував у деяких гольфах.
миль

3

Фуе , 30 байт

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

1)2:[[2:])~)~:~[[1]:~))~:~~]~]

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

Наведене вище друкує нескінченний список цифр як контрольних кодів. На 34 байти він може надрукувати фактичні цифри:

49)50:[[50:])~)~:~[[49]:~))~:~~]~]

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

В іншому поясненні використовується остання версія.

Короткий зміст елементів Fueue

Черга Fueue може містити такі елементи елементів:

  • Цілі особи, які друкують свою кодову точку Unicode при виконанні,
  • Блоковані підпрограми блоки з квадратними дужками , які милосердно неактивні (просто переходять до кінця черги), якщо )функція їх не розблоковує , і
  • Односимвольні функції, які виконуються, якщо за ними дотримується правильний тип аргументів і в іншому випадку залишаються неактивними.
    • Єдиними функціями, які використовуються в цій програмі, є ~(поміняти два наступні елементи), :(дублювати наступний елемент) та )(блокувати наступний блок).

Огляд високого рівня

Під час основного циклу програми черга складається з:

  • ланцюжок блоків, що представляють цифри, які слід повторити;
    • Цифра 1 або 2 представлена ​​блоками [49]і [50:], відповідно.
  • головний цикл, що повторюється, що повторюється, який обходить цифрові блоки та ставить чергування 1 та 2 після них, а потім розблоковує їх.
    • Розблокований розрядний блок друкує власну цифру d , а потім створює d копії наступного блоку, створюючи таким чином цифри для прогону, який він описує.

Низький рівень трасування перших 10 команд

Cmds   Explanation              Queue
49     Print '1'.               )50:[[50:])~)~:~[[49]:~))~:~~]~]
)      Inactive, move to end.   50:[[50:])~)~:~[[49]:~))~:~~]~])
50     Print '2'.               :[[50:])~)~:~[[49]:~))~:~~]~])
:[...] Duplicate block.         )[[50:])~)~:~[[49]:~))~:~~]~][[50:])~)~:~[[49]:~))~:~~]~]
)[...] Deblock (rmv. brackets). [[50:])~)~:~[[49]:~))~:~~]~][50:])~)~:~[[49]:~))~:~~]~
[...]  Inactive.                [50:])~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~]
[50:]  Inactive.                )~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:]
)      Inactive.                ~)~:~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])
~)~    Swap ) and ~.            :~[[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])~)
:~     Duplicate ~.             [[49]:~))~:~~]~[[50:])~)~:~[[49]:~))~:~~]~][50:])~)~~

Проведення повної ітерації основної петлі

Необов’язковий пробіл вставлено для окремих команд.

49 ) 50 :[[50:])~)~:~[[49]:~))~:~~]~]

Цикл 1: 49відбитки 1. )неактивний, чекаючи, коли він буде з'єднаний з основним блоком циклу. 50відбитки 2. :дублює основний блок циклу (який потребує копії для самовідтворення.)

) [[50:])~)~:~[[49]:~))~:~~]~] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 2: )розблокує перший основний блок циклу, змушуючи його почати виконувати наступний цикл.

[50:] ) ~)~ :~ [[49]:~))~:~~] ~[[50:])~)~:~[[49]:~))~:~~]~]

Цикл 3: [50:]являє собою першу цифру, вироблену в ланцюзі, ще 2не розблоковану. Наступне ), зрештою, зробить це після того, як решта основного циклу пройде його. ~)~:~- це затримка на один цикл (за допомогою заміни та копії) затримка на один цикл ~)~~. [[49]:~))~:~~]неактивний. ~замінює наступний основний блок циклу повз [50:]цифровий блок.

) ~)~ ~[[49]:~))~:~~][50:] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 4: )все ще чекає, ~)~виробляє ~), ~заміняє [[49]:~))~:~~]повз [50:]цифровий блок.

) ~)[50:] [[49]:~))~:~~] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 5: ~поміняє місцями )повз [50:]цифровий блок.

)[50:] )[[49]:~))~:~~] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 6: Перший )тепер розблокує [50:]цифровий блок, наступний - )блокує підпрограму [[49]:~))~:~~].

50 :[49] :~ ) ) ~:~ ~[[50:])~)~:~[[49]:~))~:~~]~]

Цикл 7: 50друкує 2, :дублює щойно створений [49]цифровий блок, створюючи пробіг у два 1s. :~))~:~- затримка на один цикл ~~))~:. ~міняє залишився основний блок циклу повз перший [49].

[49] ~~) ) ~:[49] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 8: ~~))затримка на один цикл )~). ~заміни :повз поточно пройдений [49].

[49] ) ~)[49] :[[50:])~)~:~[[49]:~))~:~~]~]

Цикл 9: ~міняє місцями )минуле [49]. :дублює основний блок циклу.

[49] )[49] )[[50:])~)~:~[[49]:~))~:~~]~] [[50:])~)~:~[[49]:~))~:~~]~]

Цикл 10: Перший )блокує [49]цифровий блок щойно пройденого, другий )перезапускає основну петлю для проходження наступної (вище показано на початку черги.)


Хороша робота! Причиною я дізнався якусь фую та відповів на виклик HW, тому що я насправді розглядав це завдання, але в кінці кінців був занадто заляканий природою, що базується на черзі. Це дійсно чудова оцінка для Fueue! :)
Мартін Ендер

3

x86, 41 37 35 33 28 байт

Мені було дуже весело возитися з різними інструкціями x86, оскільки це моя перша "нетривіальна" відповідь x86. Я насправді спочатку дізнався x86-64, і я врятував багато байт, просто перетворивши свою програму в 32-бітну.

Виявляється, алгоритм, який я використовував від OEIS, висуває значення масиву, що робить його придатним до x86 і зберігає значення на стеку (зверніть увагу, що MIPS не має інструкцій щодо стеку).

В даний час програма приймає Nзначення як вхідні дані ecxі повертає адресу ebpмасиву з n-м елементом, що представляє n-е значення в послідовності. Я припускаю, що повернення на стек та обчислення додаткових значень є дійсним (ми вважаємо, що поза масивом як сміття).

Журнал змін

  • -4 байт шляхом обчислення x = 2 - n%2з xorкожної ітерації

  • -2 байти, використовуючи do-while замість циклу while.

  • -2 байти, натиснувши початкові значення 1, 2, 2 за допомогою eax

  • -5 байт, не зберігати в nявному вигляді , а замість запуску циклу Nраз

.section .text
.globl main
main:
        mov     $10, %ecx           # N = 10 

start:
        mov     %esp, %ebp          # Save sp
        push    $1
        push    $2                  # x = 2
        pop     %eax       
        push    %eax                # push 2
        push    %eax                # push 2
        mov     %esp, %esi          # sn = stack+3 addr

loop:                               
        xor     $3, %al             # flip x between 1 <-> 2 
        push    %eax                # push x      
                                    # maybe use jump by parity?
        cmp     $2, (%esi)          # if *sn == 2 
        jne     loop1
        push    %eax                # push x

loop1: 
        sub     $4, %esi            # sn += 1
        loop    loop                # --N, do while (N)
end:
        mov     %ebp, %esp          # Restore sp
        ret

Objdump:

00000005 <start>:
   5:   89 e5                   mov    %esp,%ebp
   7:   6a 01                   push   $0x1
   9:   6a 02                   push   $0x2
   b:   58                      pop    %eax
   c:   50                      push   %eax
   d:   50                      push   %eax
   e:   89 e6                   mov    %esp,%esi

00000010 <loop>:
  10:   34 03                   xor    $0x3,%al
  12:   50                      push   %eax
  13:   83 3e 02                cmpl   $0x2,(%esi)
  16:   75 01                   jne    19 <loop1>
  18:   50                      push   %eax

00000019 <loop1>:
  19:   83 ee 04                sub    $0x4,%esi
  1c:   e2 f2                   loop   10 <loop>

0000001e <end>:
  1e:   89 ec                   mov    %ebp,%esp
  20:   c3                      ret 

3

C (gcc) , 72 71 65 64 62 байт

-9 байт завдяки @ceilingcat

x,y;f(z){for(x=y=-1;putchar(49-~x%2);y=-~y|z&x/2)x^=z=y&~-~y;}

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

Генерує значення послідовності безстроково (варіант 3 з виклику)


Пояснення будь ласка! Я поняття не маю, як це працює. Немає масиву! І цифри залишаються занадто малими, щоб містити один як біт.
Ørjan Johansen

@ ØrjanJohansen Я повинен визнати, я навіть не знаю, як це працює! :) Я взяв реалізацію python від OEIS A000002 , переніс його на C та гольф :)
vazt

Ах, я подумав, що там щось було, але я не заглянув досить далеко вниз на цю сторінку, щоб знайти Python. Є посилання на пояснення , але воно було трохи закопане у розділі посилань. Цей метод, безумовно, відповідає як мінімум також.
Ørjan Johansen

1) 56 байт у PHP : for($x=$y=-1;;$y=$y+1|$f&.5*$x^=$f=$y&-$y-2)echo$x&1?:2;. 2) 50-x%2повинен зберегти один байт для вас. 3) я намагався змусити його працювати x=y=1; але поки що не міг зробити операції. Можеш ти?
Тит


2

Javascript ES6 - 71 70 68 байт

(_="122")=>{for(x=1;;_+=(1+x%2)*(_[x]>1?11:1))console.log(_[++x-2])}

1 біт збережено завдяки Нілу

Танки для Shaggy для виправлення моєї помилки, а також для економії 1 біта.

f = (_="122") => {
  for(x=1;x<20;_+=(1+x%2)*(_[x]>1?11:1))
    document.getElementById('content').innerHTML += '   ' + _[++x-2]
}
f()
<div id="content"></div>


Це схоже на порт моєї відповіді Java 8 (крім x=0замість цього x=1), але @Shaggy справді вірно: це не працює в його нинішньому вигляді (я додав ,i=100;i-->0тимчасово, щоб просто побачити перші 100 елементів, замість того, щоб зачекайте 60 секунд, перш ніж побачити вихід). Не маю ідеї, чому це не працює. JS - це не моя річ.
Кевін Круїссен

Проблеми полягають у: 1.ініціюванні xдо 0 замість 1 (як згадував @KevinCruijssen) та 2.перевірка того, чи xсимвол у рядку, який може колись бути 1 або 2, більший за 49.
Shaggy

2
Ось перероблена версія (але не повністю перевірена) версія фіксованого рішення: tio.run/…
Shaggy

(_[x]*10-9)ніж(_[x]>1?11:1)
l4m2

2

Яблучне насіння , 89 байт

(def K(lambda()(concat(q(1 2))(drop 2(flatten(zip-with repeat-val(cycle(q(1 2)))(K)))))))

Визначає функцію, Kяка не бере аргументів, і повертає послідовність Колакоскі як нескінченний список. Спробуйте в Інтернеті!

Цей підхід був натхненний абсолютно нелюдською відповіддю Хаскелла . Мій оригінальний підхід був довшим і, ймовірно, був O (2 ^ n). : ^ П

Безумовно

(def kolakoski
 (lambda ()
  (concat (list 1 2)
   (drop 2
    (flatten
     (zip-with repeat-val
      (cycle (list 1 2))
      (kolakoski)))))))

Список повернення починається з (1 2). Після цього сформувати решту (читаючи зсередини назовні):

  • Рекурсивно закликайте (kolakoski)отримати список послідовностей Колакоскі (через ледачу оцінку, неважливо, що список ще не повністю сформований)
  • (cycle (list 1 2)) створює нескінченний список (1 2 1 2 1 2 ...)
  • З’єднайте два нескінченні списки разом за допомогою функції repeat-val. Це повториться 1або 2зі cycleсписку один або два рази залежно від пов'язаного значення у списку Колакоскі. Результат:((1) (2 2) (1 1) ...)
  • flatten цей список у (1 2 2 1 1 ...)
  • Перші два терміни ми вже отримали (concat (list 1 2), тому dropперші два із створеного списку ми уникаємо, щоб уникнути дублювання.

2

Стакс , 12 байт

╦╥2Bïß▄n»-[╒

Запустіть і налагоджуйте його

Це представлення ascii тієї самої програми.

G@}2R;D{|;^]*m$

Він розширює послідовність x разів, де x - вхід. Потім він виводить x- й елемент, індексований 0.

G }             G jumps to trailing } and returns when done
 @              get xth element in array
   2R           [1, 2]
     ;D         repeat the rest x times
       {     m  map array using block
        |;^]    produces [1] and [2] alternately
            *   repeat array specified number of times
              $ flatten array

Ось бонусне 12-байтове рішення, яке видає вихід у вигляді нескінченного потоку. Натисніть Виконати, щоб почати.


2

R, 63 байт або 61 байт

Реалізація 1: друкує n- й член послідовності.

x=scan()
a=c(1,2,2)
for(n in 3:x)a=c(a,rep(2-n%%2,a[n]))
a[x]

Реалізація 2: друкує перші n термінів послідовності.

x=scan()
a=c(1,2,2)
for(n in 3:x)a=c(a,rep(2-n%%2,a[n]))
a[1:x]

(Різниця лише в останньому рядку.)

Так, так, ви можете поскаржитися, що моє рішення неефективне, що воно обчислює дійсно більше термінів, ніж потрібно, але все ж ...

Оновлення: Дякуємо @Giuseppe за бриття 9 байт.


1
використовуйте a=c(a,rep(2-n%%2,a[n]))замість другої forпетлі, щоб відголити деякі байти.
Джузеппе

@Giuseppe Реалізовано, дякую!
Андрей Костирка

Ми не заперечуємо проти неефективних рішень для гольфу тут. Насправді використання більш неефективного алгоритму є однією з підказок у wiki - тезі code-golf .
Ørjan Johansen

2

Мова програмування Шекспіра, 575 байт (але дефектний) або 653 або 623 байт

,.Puck,.Ford,.Act I:.Scene X:.[Enter Puck and Ford]Ford:You big cat!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you nicer zero?If not,let us Scene X.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

У гарячій суперечливій категорії SPL це перемогло б поточний запис Джо Кінга (583 байти), за винятком того, що він несправний: По-перше, він не працює у версії TIO (впроваджуючи веб-сайт SPL) - але він працює у Perl версія , тому, можливо, це не є серйозним дефектом. По-друге, хоча перші дві цифри не друкуються. Якби ми допустили цей дефект у рішенні Джо Кінга, то це несправне рішення склало б 553 байти, побивши моє несправне рішення.

Моє рішення не працює в TIO з двох причин: ми намагаємося покладатися на порожній стек, що повертає нуль, коли з'являється; і ми вирушаємо на першу сцену, з "[Введіть Форд та Пук]", хоча ніхто не покинув сцену. Це лише попередження у версії Perl. Якщо я виправлю ці помилки і вставте перші дві цифри, я досягну 653 байт:

 ,.Puck,.Ford,.Act I:.Scene I:.[Enter Puck and Ford]Ford:You cat!Open heart!You big cat!Open heart!You zero!Scene X:.Ford:Remember you!You big cat!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you nicer zero?If not,let us Scene X.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

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

Я можу генерувати повну послідовність у реалізації Perl, використовуючи 623 байти:

,.Puck,.Ford,.Act I:.Scene I:.[Enter Puck and Ford]Ford:You cat!Open heart!You big cat!Open heart!Scene L:.Ford:Is I nicer zero?If so,let us Scene V.Is you nicer a big cat?If so,you is the sum of you a big lie.If so,open heart!Open heart!Scene M:.Puck:Remember you!Is I nicer a cat?You big cat.If so,you cat.Ford:Recall!Is you worse a cat?If so,you big cat!If so,let us Scene L.Is you nicer a big cat?If not,let us Scene M.You is the sum of you a big lie.Scene V:.Ford:Remember you!Is you worse a big big cat?If not, you big cat.Is you as big as a big cat?If not,you zero.You is the sum of I you.Puck:Recall!Let us Scene L.

Однак я зазначу, що це рішення швидко порівняно з багатьма іншими рішеннями і використовує логарифмічні обсяги пам'яті, а не зберігання всього списку. (Це схоже на рішення Вазта С, до якого воно віддалено пов'язане.) Це не має значення для гольфу, але я задоволений цим навіть. Ви можете генерувати мільйон цифр приблизно за хвилину в Perl (наприклад, якщо ви збираєтесь на sed і wc, щоб отримати підрахунок цифр), де інше рішення може дати вам кілька тисяч цифр.

Пояснення

Ми зберігаємо послідовність змінних у порядку: стек Puck (знизу вгору), значення Puck, значення Ford, стек Ford (зверху вниз). Окрім нульових значень на кінцях (з нулем зліва, можливо, від появи порожнього стека), кожне значення - це цифра, що формується наступним у цьому поколінні, при цьому додається 2, якщо наступне покоління має мати ще одну дитину від цього батька. Коли у нас є N ненульових значень у послідовності, ми генеруємо всіх дітей до N-го покоління та включаємо їх у своєрідний обхід дерева на глибині. Ми друкуємо значення лише з N-го покоління. Коли N-го покоління було повністю сформовано, збережені значення насправді є початковими значеннями для поколінь 2 до (N + 1), тому ми додаємо 2 зліва і починаємо знову, на цей раз генеруючи (N + 1) ) -го покоління.

Отже, контур: Сцена X: Коли ми досягнемо тут, це початок нового обходу. Шайба == 0. Ми необов'язково підсуваємо цей нуль до стека Puck і встановлюємо Puck = 2. Сцена L: Якщо Ford == 0, ми дійшли до друкарського покоління. Якщо ні, goto V. Для друку, якщо значення в Puck було додано 2, вийміть 2 та надрукуйте його двічі; якщо ні, то надрукуйте його один раз. Сцена M: Це цикл, де ми неодноразово перемикаємо значення Puck і повертаємося назад через послідовність. Повторюємось, поки або не досягнемо кінця (Puck == 0), і в цьому випадку перейдемо до X, або досягнемо значення, яке потребує іншої дитини (Puck> 2), і в цьому випадку віднімаємо зайві 2 і рухаємось уперед у V. Сцена V: Ось ми йдемо вперед. Якщо Puck 2 або 4, наступне покоління буде містити двох дітей від поточного батька, тому Ford + = 2. Крок вперед через послідовність. Перейдіть на L, щоб перевірити його на припинення.


1

аксо , 13 байт

[:|[1+{#;1;-_

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

Пояснення

Це почалося як порт альтернативного рішення у моїй відповіді Wumpus :

2%)[=]&=[O00.

Це призвело до 18 байт. Я закінчив гольфувати його до 13 байтів, які ви бачите вище, щоб пристосувати його більше до того, як працює аксо. Потім ця 13-байтна версія надихнула поліпшення до 11 байт у Wumpus, так що тепер фактично ближче до цієї версії.

Як і в Wumpus, в ітерації i , внизу стеку міститься (i) -1, а вгорі міститься перший елемент i- го прогону, але ми працюємо з 0 і 1 у всьому, крім друку.

[:    Store a copy of the top of the stack in register A.
|     Pull up a(i)-1 from the bottom of the stack.
[1+{  Print a(i).
#;    If a(i)-1 is 1, push the value in register A.
1;-   Push another copy of that value and subtract it from 1 to swap
      0 and 1 for the next run.
_     Jump back to the beginning of the program.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.