计算科拉科斯基序列


54

这是旧挑战的转折,以便将I / O要求调整为我们最近的标准。这样做是为了允许更多的语言参与有关此流行序列的挑战。有关重新发布的讨论,请参见此元发布。

Kolakoski序列是一个有趣的自引用序列,荣幸地成为OEIS序列A000002(比A000001更易于理解和实现)。序列以1开头,仅由1 s和2 s组成,序列元素a(n)描述序列中第n1 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个项,其中n01开始
  2. 取的输入Ñ和输出的术语直到并包括所述Ñ个的序列,其中的术语ñ开始无论是从01(即,或者打印第一Ñ或第一n + 1个方面)。
  3. 无限期地从序列中输出值。

在第二种和第三种情况下,您可以选择任何合理,明确的列表格式。如果元素之间没有分隔符,那是很好的,因为根据定义它们始终是一位数字。

在第三种情况下,如果提交的内容是函数,则还可以使用支持它们的语言返回无限列表或生成器。

您可以编写程序或函数,并使用我们的任何标准方法来接收输入和提供输出。请注意,默认情况下,这些漏洞是禁止的。

这是,因此以字节为单位的最短有效答案为准。


相关,但不是欺骗。
魔术章鱼缸

问题的一般化,但是由于序列的初始部分是固定的,因此可能可以进行优化。
朱塞佩

在我们讨论的同时,我也得到了另一种概括
马丁·恩德

Answers:


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的列表。第一个元素是Kolakoski序列的第一个元素。

链的第二次调用循环重复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的列表。前两个元素是Kolakoski序列的前两个元素。

该过程将继续进行三个迭代。

   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遍历列表时构建列表。对于每个条目xl,附加x的拷贝12两者中的当前最后一个元件相对。

主要困难在于处理初始的自我指称片段[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

Wumpus13 11字节

=[=)O?=!00.

在线尝试!

无限打印无分隔符的序列。

我对这有多短感到惊讶。

说明

基本思想是将序列保留在堆栈上,并反复使用最底部的元素来生成另一个运行,然后打印它。我们实际上是在这里滥用堆栈作为队列。我们还可以通过使用0and 1(仅增加输出值)而不是1and 来节省几个字节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

Brachylog30 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

爪哇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));}

无限打印,不带定界符。

@Neil间接提示后的-3个字节。
-5个字节,感谢@MartinEnder
-3字节将Java 8转换为Java 10。

说明:

在线尝试(在TIO上60秒后超时)。

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
我喜欢您如何简化外观。
暴民埃里克(Erik the Outgolfer)

@EriktheOutgolfer谢谢!:)当我阅读挑战时,我不知道该如何开始,但是后来就打了我(使用带有首字母的列表,[1,2,2]然后从那里开始),然后我写了一个155字节的答案(现在通过使用String打高尔夫球)而不是列表)。
凯文·克鲁伊森

为什么不使用(3-i)代替(1+i%2)
暴民埃里克(Erik the 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)

在线尝试!

ØrjanJohansen使用不可辩驳的模式来强​​制前缀,从而节省了7个字节。


5
通过使其变得懒惰,可以节省7个字节。在线尝试!
与Orjan约翰森

@ØrjanJohansen太神奇了,懒惰模式对我来说是神奇的。要发布您自己的答案吗?
xnor

不,你在那儿。通过n:在表达式的开头使用,您不需要知道在x哪里产生第一个n。但是您需要使模式变得懒惰,以避免函数在进入之前对其进行检查n:
与Orjan约翰森

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

莎士比亚编程语言594583572字节

感谢Ed Wynn提供了-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!

在线尝试!

这是Ed Wynn的非高尔夫解决方案的高尔夫版本,从他在评论中链接的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!

真好!通过将单个子代设为(-1或0)而不是双胞胎,可以节省7个字节。这会在场景X之前(当“如果这样”变为“如果不是”时)花费1个字节,而在场景X循环之后(当“是否更好”变成“为零更好”时)会花费另一个字节。节省的是,您可以替换“如果不,请记住!” 只需“记住我!” 早一行。我们插入第二个孩子或备用终止符。(这就是为什么您需要更改非常平衡的“我好吗?” —在场景X之后您不再可以依赖Ford == 0。)这是TIO,587字节:tinyurl.com/yb9zg4gp
Ed永利

您可以删除场景L中的第一个“如果是”,并将命令移至场景V的开头。这仅节省了1个字节,因为您需要一个新的“福特:”。但是,只要可以依赖于福特自动零初始化,就可以在场景I中保存几个字节。您无权依赖它,但它可能起作用:这是TIO,584字节:tinyurl.com/y9f6vy7u
Ed Wynn,


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))

感谢tsh抓痒的大脑,节省了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

谢谢,@ tsh。s[n]||很明显没有看到树木的树木!第二个建议无效,因为该函数只能调用一次;sx需要在每次通话时进行初始化。
毛茸茸的

第二个不被重用,只要sx由每个所调用之间其他码(这是默认情况下)没有触及。
tsh

1
真好!s[x]+0-9是一个很好的技巧
JollyJoker

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
您可以(可能是,我没有测试过)在备用版本中通过[1,2,2]作为sum
Rod 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

05AB1E12 9字节

多亏了Grimy,节省了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的情况下打印前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:虽然我没有生产前三件产品,但是不幸的是打印无法正常工作
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次(^:]),就可以了。(查看其他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]:~))~:~~]~]

在线尝试!

其余的解释使用后一种版本。

元素要素汇总

队列队列可以包含以下类型的元素:

  • 整数,在执行时会打印其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]数字块,并运行2 1s。:~))~:~是的一个周期延迟~~))~:~交换第一个之后的剩余主循环块[49]

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

周期8:~~))是的单周期延迟)~)~交换:经过当前遍历的[49]

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

周期9:~交换)过去[49]:复制主循环块。

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

循环10:第一个)循环对[49]刚刚遍历的数字块进行解块,第二个)循环重新启动主循环以遍历下一个(在队列开始处显示)。


干得好!之所以我学到一些Fueue并回答了HW挑战的原因是因为我实际上是为应对这一挑战而研究的,但最终因基于队列的本质而被吓倒了。对于Fueue来说,这真的是一个很大的分数!:)
Martin Ender '18

3

86,41个 37 35 33 28字节

我玩弄不同的x86指令很有趣,因为这是我的第一个“平凡”的x86答案。我实际上是首先学习x86-64的,仅通过将程序转换为32位就节省了很多字节。

事实证明,我从OEIS中使用的算法将值推送到数组,这使其适合x86并将值存储在堆栈上(请注意,MIPS没有堆栈指令)。

当前,程序将N值作为输入,ecx并返回ebp数组的地址in ,其中第n个元素代表序列中的第n个值。我假设返回堆栈并计算额外的值是有效的(无论如何,我们认为超出数组的内容都是垃圾)。

变更日志

  • -4字节通过计算x = 2 - n%2xor每个迭代

  • 通过使用do-while而不是while循环来获得-2字节。

  • 通过使用以下方式推送初始值1、2、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)


请解释!我不知道这是如何工作的。没有数组!而且数字太小而不能包含一位。
与Orjan约翰森

我必须承认@ØrjanJohansen,我也不知道这是如何工作的!:)我从OEIS A000002中获取了python实现,将其移植到C并对其进行了高尔夫球处理:)
vazt

啊,我以为那里可能有东西,但在该页面上看起来不足以找到Python。这里有一个解释的链接,但是在链接部分有一些掩盖。此方法肯定至少也适合C。
与Orjan约翰森

1)PHP中的56个字节: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])}

感谢Neil,节省了1位

Tanks to 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字符串中的th字符(只能是1或2)是否大于
49。– Shaggy

2
这是固定解决方案的简化版本(但未经全面测试):tio.run/…
Shaggy

(_[x]*10-9)(_[x]>1?11:1)
l4m2 '18年

2

苹果种子,89字节

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

定义一个K不带参数的函数,并将Kolakoski序列作为无限列表返回。在线尝试!

这种方法的灵感来自全人类的Haskell回答。我最初的方法更长可能是O(2 ^ n)。:^ P

不打高尔夫球

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

返回列表以开头(1 2)。之后,生成其余部分(从内到外读取):

  • 递归调用(kolakoski)以获取Kolakoski序列列表(由于延迟评估,列表尚未完全生成无关紧要)
  • (cycle (list 1 2)) 创建一个无限列表 (1 2 1 2 1 2 ...)
  • 使用函数将两个无限列表压缩在一起repeat-val。这将重复12cycle列表中一个或两个时间取决于在Kolakoski列表关联的值。结果:((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是输入。然后,它输出 0个索引的 x 元素。

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实现了,谢谢!
安德烈KOSTYRKA

我们不介意这里打高尔夫球的解决方案效率低下。实际上,使用效率更低的算法是代码高尔夫标签Wiki中的技巧之一。
与Orjan约翰森

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类别中,它有缺陷,它将胜过Jo King的当前条目(583字节):首先,它不能在TIO版本中运行(实现SPL网站)-但它确实在Perl中运行版本,所以这可能不是一个严重的缺陷。但是,第二,它不打印前两位数字。如果我们允许Jo King解决方案中存在该缺陷,那么该缺陷解决方案将为553字节,超过我的缺陷解决方案。

我的解决方案在TIO上失败的原因有两个:我们试图依靠一个空栈,当弹出时该栈返回零。即使没有人离开舞台,我们还是以“ [Enter Ford and 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.

在线尝试!

我可以使用623个字节在Perl实现中生成完整序列:

,.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.

但是,我要指出的是,这种解决方案很快与许多其他解决方案相比,并且使用对数的内存而不是存储整个列表。(这与vazt的C解决方案很相似,与之密切相关。)这对高尔夫没有什么影响,但即使如此我也很满意。您可以在大约一分钟的时间里在Perl中生成一百万个数字(例如,如果通过管道传输到sed和wc以获取数字计数),那么其他解决方案可能会为您提供几千个数字。

说明

我们按顺序存储一系列变量:Puck的堆栈(从下至上),Puck的值,Ford的值,Ford的堆栈(从上至下)。除了结尾处的零值(左边的零可能会弹出一个空堆栈)之外,每个值都是该一代中下一个生成的数字,如果下一代需要从该父对象中再生一个孩子,则添加2。当序列中有N个非零值时,我们会以一种深度优先的树遍历的方式生成所有子级,直到第N代(包括第N代)。我们仅打印第N代的值。当第N代已完全生成时,实际上存储的值是第2代到(N + 1)的起始值,因此我们在左侧附加2并再次开始,这一次生成了(N + 1 )th代。

因此,概述:场景X:到达此处时,这是新遍历的开始。冰球== 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

axo,13个字节

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

在线尝试!

说明

这最初是我的Wumpus答案中的替代解决方案的移植:

2%)[=]&=[O00.

这导致了18个字节。我最终将其打高尔夫球到您在上面看到的13个字节,以便根据axo的工作方式进行更多调整。然后,这个13字节的版本最终激发了Wumpus中11字节的改进,因此实际上它更接近该版本。

与Wumpus一样,在迭代i中,堆栈的底部保留a(i)-1,而顶部保留第i次运行的第一个元素,但是除了打印之外,我们一直在使用01

[:    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.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.