Вычислить последовательность Колакоски


54

Это перепост старой проблемы , чтобы приспособить требования ввода / вывода к нашим недавним стандартам. Это сделано для того, чтобы позволить большему количеству языков принять участие в соревновании об этой популярной последовательности. Смотрите этот мета-пост для обсуждения репоста.

Последовательность Колакоски представляет собой забавную самоссылочную последовательность, которая имеет честь быть последовательностью OEIS A000002 (и ее гораздо легче понять и реализовать, чем A000001). Последовательность начинается с 1 , состоит только из 1 с и 2 с, а элемент последовательности a (n) описывает длину n- го цикла 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,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 (т.е. либо напечатать первую п или первый N + 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, потому что таким образом нам не нужно явно инициализировать стек с помощью a, 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

Brachylog , 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
Мне нравится, как вы сделали этот взгляд таким простым.
Эрик Outgolfer

@EriktheOutgolfer Спасибо! :) Когда я прочитал задание, я не был уверен, с чего начать, но потом он поразил меня (используя список с начальным [1,2,2]и последующим ), и я написал 155-байтовый ответ (который теперь обрабатывается с помощью строки вместо списка).
Кевин Круйссен

Почему бы не использовать (3-i)вместо (1+i%2)?
Эрик Outgolfer

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)

Попробуйте онлайн!

Эрджан Йохансен сохранил 7 байтов, используя неопровержимый шаблон для принудительного использования префикса.


5
Вы можете сэкономить 7 байт, сделав его ленивее. Попробуйте онлайн!
Орджан Йохансен,

@ ØrjanJohansen Это удивительно, и ленивый узор для меня волшебен. Хотите опубликовать свой ответ?
xnor

Нет, ты был там почти весь путь. Используя n:в начале выражения, вам не нужно знать, что xесть, чтобы произвести первое n. Но вам нужно, чтобы шаблон был ленивым, чтобы функция не проверяла его перед тем, как перейти к n:.
Орджан Йохансен,

6

Gol> <> , 8 7 байт

:{:PnKz

Попробуйте онлайн!

объяснение

Это порт моего ответа от Wumpus . Gol> <> - это в основном язык, который обладает всеми необходимыми функциями для переноса ответа Wumpus (в частности, неявных нулей в нижней части стека, «дублирующихся» реализованных «pop, push, push» и командой вращения стека), но :

  • У него есть тороидальная сетка, что означает, что нам не нужно явное, 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 (когда «если так» становится «если нет»), и еще один байт сразу после цикла сцены X (когда «я лучше вас» становится «лучше ноль»). Экономия в том, что вы можете заменить «Если нет, помните вас!» просто "Помни меня!" на одну строку раньше. Мы вставляем либо второго ребенка, либо запасного терминатора. (Вот почему вам нужно изменить точно сбалансированное «Я лучше вас?» - вы больше не можете полагаться на Ford == 0 после сцены X.) Вот TIO, 587 байт: tinyurl.com/yb9zg4gp
Ed Винн

Вы можете удалить первое «Если так» в сцене L и переместить команду в начало сцены V. Это сэкономит вам только 1 байт, потому что вам нужен новый «Ford:». Но вы сохраняете пару байтов в сцене I, если вы можете полагаться на то, что Ford будет автоматически инициализироваться нулем. Вы не имеете права полагаться на это, но это может сработать: вот TIO, 584 байта: tinyurl.com/y9f6vy7u
Эд Винн,

5

> <> , 13 12 байт

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

Попробуйте онлайн!

Порт Мартена Эндера Wumpus ответ . К сожалению, ><>не имеет команды приращения или инвертирования, а также не имеет неявных нулей в нижней части стека, поэтому в итоге получается немного длиннее.


1
Да, это то, что я имел до того, как вспомнил Гол> <>. :)
Мартин Эндер

5

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

Ну, это заставило мой мозг чесаться больше, чем следовало! Возвращает n0-й член, индексируется 0.

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

5 + 1 байт сэкономлено благодаря царапинам моего зудящего мозга!


Проверь это

Фрагмент ниже выведет первые 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)
TSH

Кстати, s='122',x=1,g=n=>s[n]||g(n,s+=(++x%2+1)*(10*s[x]-9))считается действительным представлением?
ч. В

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

второй делает многократное использование, до тех пор , как sи xне трогали другие коды между каждым вызывает (что по умолчанию).
ч. В

1
Приятно! s[x]+0-9довольно
приятный

4

Python (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 байт

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

Попробуйте онлайн!

Печатает числа в виде кодов символов бесконечно. Для ясности, вот версия, которая печатается в цифрах (за исключением первых двух элементов, которые достаточно легко проверить).

Как это устроено:

+.+. 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 байта благодаря Грими

Печатает первые 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ÅΓ.
Grimmy

Или еще лучше ∞[2LÞsÅΓ.
Grimmy

Или Δ2LÞsÅΓI∍для версии, которая печатает первые n элементов с заданным значением input n.
Grimmy

@ Грими: Спасибо! Мне нравится первая n версия, так как она действительно заканчивается :)
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 раз. Мы будем использовать его для начальной загрузки последовательности Колаковского из исходного семени. Каждый шаг будет выполняться следующим образом:

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 раз ( ^:]), все будет хорошо. (Проверьте эти другие последовательности OEIS для получения дополнительной информации: длины генерации , частичные суммы .)

Как только мы это сделаем, все, что нам нужно сделать, это взять первые n терминов, используя $. Конструкция $vдля любого глагола vявляется примером ловушки, и приведение его в nкачестве аргумента будет выполнено n $ (v n).

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


Ох, это прекрасно работает с I.. Я всегда хотел, чтобы функция копирования использовалась в каком-то гольфе.
миль

3

Fueue , 30 байт

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

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]блок цифр, создавая серию из двух 1с. :~))~:~задержка один цикл ~~))~:. ~переставляет оставшийся блок основного цикла после первого [49].

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

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

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

Цикл 9: ~свопы )прошлое [49]. :дублирует основной блок цикла.

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

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


Хорошо сделано! Причина, по которой я выучил немного Fueue и ответил на вызов 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 из вызова)


Пояснения пожалуйста! Я понятия не имею, как это работает. Там нет массива! И числа остаются слишком маленькими, чтобы содержать один бит.
Орджан Йохансен

@ ØrjanJohansen Должен признаться, я тоже понятия не имею, как это работает! :) Я взял реализацию Python от OEIS A000002 , портировал его на C и поиграл в гольф :)
vazt

Ах, я подумал, что это могло быть что-то там, но недостаточно заглянул в эту страницу, чтобы найти Питона. Есть ссылка на объяснение , но она была немного похоронена в разделе ссылок. Этот метод определенно подходит C, по крайней мере, также.
Эрджан Йохансен

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 бит спасен благодаря Нилу

Танки Шегги за исправление моей ошибки, а также за сохранение 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.инициализация x0 вместо 1 (как упомянуто @KevinCruijssen) и 2.проверка, является ли xth-й символ в строке, который может быть только 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которая не принимает аргументов и возвращает последовательность Колакоски в виде бесконечного списка. Попробуйте онлайн!

Этот подход был вдохновлен ответом Haskell от полностью человека . Мой оригинальный подход был длиннее и, вероятно, был O (2 ^ n). : ^ P

Ungolfed

(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

Stax , 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-байтовое решение, которое производит вывод в виде бесконечного потока. Нажмите Run, чтобы начать.


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 Реализовано, спасибо!
Андрей Костырка,

Мы не против неэффективных решений для игры в гольф. Фактически, использование более неэффективного алгоритма является одним из советов в теге code-golf wiki .
Эрджан Йохансен

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 по двум причинам: мы пытаемся опираться на пустой стек, возвращающий ноль при извлечении; и мы идем в первую сцену с «[Введите Ford и Puck]», хотя никто не покинул сцену. Это всего лишь предупреждения в версии 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.

Тем не менее, я хотел бы отметить, что это решение быстро по сравнению со многими другими решениями и использует логарифмические объемы памяти, а не сохраняет весь список. (Это похоже на C-решение vazt, с которым оно связано отдаленно.) Это не имеет значения для гольфа, но я доволен этим, несмотря на это. Вы можете генерировать миллион цифр примерно за минуту в Perl (например, если вы отправляете по конвейеру sed и wc, чтобы получить счетчик цифр), где другое решение может дать вам несколько тысяч цифр.

объяснение

Мы сохраняем последовательность переменных в следующем порядке: стек Пака (снизу вверх), значение Пака, значение Форда, стек Форда (сверху вниз). Помимо нулевых значений на концах (с нулем слева, возможно, от выталкивания пустого стека), каждое значение - это цифра, сгенерированная следующим в этом поколении, с 2 добавленными, если у следующего поколения должен быть другой дочерний элемент от этого родителя. Когда у нас есть N ненулевых значений в последовательности, мы генерируем все дочерние элементы вплоть до N-го поколения и включаем его в своего рода обход дерева в глубину. Мы печатаем значения только из N-го поколения. Когда N-е поколение полностью сгенерировано, сохраненные значения фактически являются начальными значениями для поколений 2 - (N + 1), поэтому мы добавляем слева 2 и начинаем снова, на этот раз генерируя (N + 1) ) -го поколения.

Итак, набросок: Сцена X: Когда мы достигаем здесь, это начало нового обхода. Puck == 0. При желании мы помещаем этот ноль в стек Puck и устанавливаем Puck = 2. Сцена L: Если Ford == 0, мы достигли печатного поколения. Если нет, перейдите к 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 байтами, которые вы видите выше, чтобы настроить его так, как работает Axo. Затем эта 13-байтовая версия вдохновила улучшение на 11 байт в Wumpus, так что теперь она фактически ближе к этой версии.

Как и в Wumpus, в итерации i нижняя часть стека содержит a (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.