减少科拉科斯基


27

总览

你们中有些人可能知道Kolakoski序列A000002),这是一个众所周知的具有以下属性的自指代序列:

Coolio Kolakoski属性,哟。

它是一个仅包含1和2的序列,对于每组1和2,如果将游程的长度相加,则它等于自身,仅为长度的一半。换句话说,Kolakoski序列描述了序列本身的游程长度。这是唯一执行此操作的序列,只是删除了开头的1的序列相同。(仅当您将自己限制为由1和2组成的序列时才如此-Martin Ender)


挑战

面临的挑战是,给定一个整数列表:

  • 输出-1如果列表不是Kolakoski序列的工作前缀。
  • 在序列变为之前输出迭代次数[2]

解决的例子

以提供的图像为例:

[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1] # Iteration 0 (the input).
[1,2,2,1,1,2,1,2,2,1,2]             # Iteration 1.
[1,2,2,1,1,2,1,1]                   # Iteration 2.
[1,2,2,1,2]                         # Iteration 3.
[1,2,1,1]                           # Iteration 4.
[1,1,2]                             # Iteration 5.
[2,1]                               # Iteration 6.
[1,1]                               # Iteration 7.
[2]                                 # Iteration 8.

因此,所得数字8用于的输入[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1]

9 如果您要1索引,也可以。


测试套件(您也可以使用子迭代进行测试)

------------------------------------------+---------
Truthy Scenarios                          | Output
------------------------------------------+---------
[1,1]                                     | 1 or 2
[1,2,2,1,1,2,1,2,2,1]                     | 6 or 7
[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1]       | 8 or 9
[1,2]                                     | 2 or 3
------------------------------------------+---------
Falsy Scenarios                           | Output
------------------------------------------+---------
[4,2,-2,1,0,3928,102904]                  | -1 or a unique falsy output.
[1,1,1]                                   | -1
[2,2,1,1,2,1,2] (Results in [2,3] @ i3)   | -1 (Trickiest example)
[]                                        | -1
[1]                                       | -1

如果您感到困惑:

真理:最终将达到两个,而没有任何中间步骤,除了1和之外,没有其他元素2。–Einkorn Enchanter 20 hours ago

虚假:最终值不是[2]。中间术语包含集合以外的东西[1,2]。还有两件事,请参见示例。


这是,最低的字节数将是胜利者。


7
我们可以使用任何false值而不是正义值-1吗?
mbomb007

1
您所说的“不是Kolakoski序列的有效前缀”是什么意思?我以为您的意思是[2]直到我看到[2,2,1,1,2,1,2]测试用例后,列表才最终到达。
ngenisis

1
@ngenisis最终将达到两个,而没有任何中间步骤,除了1和以外,没有任何其他元素2
小麦巫师

2
添加[1]为测试用例可能是一个好主意。
Emigna

1
@ mbomb007任何不同的值都可以。正整数不是很好。如果您是1索引,则0很好。“假”很好。错误是可以的。任何非正的返回值都可以,即使是-129.42910。
Magic Octopus Urn

Answers:


8

Haskell126 87 79 76 75字节

ØrjanJohansen节省了39个字节

import Data.List
f[2]=0
f y@(_:_:_)|all(`elem`[1,2])y=1+f(length<$>group y)

在线尝试!

错误输入错误。


f(因此!)可以通过使用惰性生产+ span/ length而不是累加器大大缩短。在线尝试!
与Orjan约翰森

1
似乎为[1]
Emigna

1
@Emigna Darn。我花了6个字节来修复它,但是我已经修复了。
小麦巫师

@ØrjanJohansen这似乎是一个不错的技巧,但是我对Haskell并不足够了解,那里发生了什么。如果您愿意,可以将其发布为您自己的答案,但是至少只要不知道您的解决方案是如何工作的,就不会将其添加到我的答案中。:)
小麦巫师

1
然后我意识到,这是将进口实际上是短(也更容易理解)的情况下:import Data.List;f l=length<$>group l。(<$>map这里是同义词。)此外,与其使用两种不同的大小写形式,不如-1使用一种@(_:_:_)模式来强制主要大小写仅匹配长度大于等于2的列表。在线尝试!
与Orjan约翰森

6

05AB1E,22字节

[Dg2‹#γ€gM2›iX]2QJiNë®

在线尝试!

说明

[                        # start a loop
 D                       # duplicate current list
  g2‹#                   # break if the length is less than 2
      γ                  # group into runs of consecutive equal elements
       €g                # get length of each run
         M2›iX           # if the maximum run-length is greater than 2, push 1
              ]          # end loop
               2QJi      # if the result is a list containing only 2
                   N     # push the iteration counter from the loop
                    ë®   # else, push -1
                         # implicitly output top of stack

失败[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]

@WeijunZhou:谢谢,固定!
Emigna

您可能已经忘记更新链接了……
Zhou Weijun

1
@WeijunZhou:确实我有。再次感谢:)
Emigna '18

3

SCALA,290(282?)个字符,290(282?)个字节

我花了很长时间...但是我终于完成了!

使用此代码:

var u=t
var v=Array[Int]()
var c= -1
var b=1
if(!u.isEmpty){while(u.forall(x=>x==1|x==2)){c+=1
if(u.size>1){var p=u.size-1
for(i<-0 to p){if(b==1){var k=u(i)
v:+=(if(i==p)1 else if(u(i+1)==k){b=0
if(p-i>1&&u(i+2)==k)return-1
2}else 1)} else b=1}
u=v
v=v.take(0)}else if(u(0)==2)return c}}
c

我不知道我是否应该算var u=t入字节,考虑到我不使用t的算法中(副本是刚拿到modifyable var代替参数t视为val-感谢SCALA)。请告诉我是否应该算。

有够难。在线尝试!

PS:我当时正在考虑递归地执行此操作,但是我必须传递一个计数器作为真正的递归“子功能”的参数;这个事实使我声明了两个函数,这些字符/字节什么都没有丢失。

编辑:我不得不更改(?),因为我们不确定我们是否应该算数[1]。所以是修改后的代码:

var u=t
var v=Array[Int]()
var c= -1
var b=1
if(!u.isEmpty){try{t(1)}catch{case _=>return if(t(0)==2)0 else -1}
while(u.forall(x=>x==1|x==2)){c+=1
if(u.size>1){var p=u.size-1
for(i<-0 to p){if(b==1){var k=u(i)
v:+=(if(i==p)1 else if(u(i+1)==k){b=0
if(p-i>1&&u(i+2)==k)return-1
2}else 1)} else b=1}
u=v
v=v.take(0)}else if(u(0)==2)return c}}
c

它没有经过优化(对于相同的条件,我有一个重复的“输出”:当我到达时[2]和对param [2]进行单独处理时)。

新费用= 342(我没有故意修改标题)


1
似乎为[1]
-Emigna

是的,但是正如OP所说(至少据我所知):“删除了开头的1”和“在序列变为之前输出迭代次数[2]
V. Courtois

据我了解,[1]永远不会到达[2],因此应该返回-1
Emigna

我懂了。那么,您认为我应该在开始时设置一点条件吗?谢谢你的建议。
V. Courtois

我不知道scala,但我想您可以修改循环以在列表的长度小于2时停止。您似乎已经检查了元素的末尾是否为2。
Emigna '17

2

JavaScript,146142字节

首先尝试打高尔夫球,似乎较大功能中的“返回”非常繁琐...

另外,检查b = 1和b = 2会占用一些字节...

这是代码:

f=y=>{i=t=!y[0];while(y[1]){r=[];c=j=0;y.map(b=>{t|=b-1&&b-2;if(b-c){if(j>0)r.push(j);c=b;j=0}j++});(y=r).push(j);i++}return t||y[0]-2?-1:0^i}

说明

f=y=>{/*1*/}                                        //function definition

//Inside /*1*/:
  i=t=!y[0];                                        //initialization
                                                    //if the first one is 0 or undefined, 
                                                    //set t=1 so that it will return -1   
                                                    //eventually, otherwise i=0
  while(y[1]){/*2*/}                                //if there are 2+ items, start the loop

  //Inside /*2*/:
    r=[];c=j=0;                                     //initialization
    y.map(b=>{/*3*/});                              //another function definition

    //Inside /*3*/:
      t|=b-1&&b-2;                                  //if b==1 or b==2, set t=1 so that the
                                                    //entire function returns -1
      if(b-c){if(j>0)r.push(j);c=b;j=0}             //if b!=c, and j!=0, then push the 
                                                    //count to the array and reset counter
      j++                                           //counting duplicate numbers

    (y=r).push(j);i++                               //push the remaining count to the array
                                                    //and proceed to another stage

  return t||y[0]-2?-1:0^i                           //if the remaining element is not 2, or
                                                    //t==1 (means falsy), return -1,
                                                    //otherwise return the counter i

测试数据(使用给定的测试数据)

l=[[1,1],[1,2,2,1,1,2,1,2,2,1],[1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1],[1,2],[4,2,-2,1,0,3928,102904],[1,1,1],[2,2,1,1,2,1,2],[]];
console.log(l.map(f));
//Output: (8) [1, 6, 8, 2, -1, -1, -1, -1]

编辑1:146-> 142:撤消减少字节数的编辑,因为这会影响输出。还有一些对最后一条陈述的修改


f=a=>{for(i=t=!a[0];a[1];)r=[],c=j=0,a.map(a=>{t|=a-1&&a-2;a-c&&(0<j&&r.push(j),c=a,j=0);j++}),(a=r).push(j),i++;return t||a[0]-2?-1:0^i}节省5个字节(用于循环而不是while;逗号与花括号; &&与if)。您可以使用Google的闭包编译器(closure-compiler.appspot.com)来为您完成这些优化
Oki

2

果冻26 25 22 21 20字节

FQœ-2R¤
ŒgL€µÐĿṖ-LÇ?

在线尝试!

直到20个字节,这段代码实际上都无法正常工作,我什至没有注意到。在[2,2]测试用例上失败了。现在应该可以正常工作了。


2

的JavaScript(ES6),127 126 95 80个字节

g=(a,i,p,b=[])=>a.map(x=>3>x&0<x?(x==p?b[0]++:b=[1,...b],p=x):H)==2?i:g(b,~~i+1)

0索引。抛出"ReferenceError: X is not defined""InternalError: too much recursion"对错误的输入。

测试用例


1

Clojure,110字节

#(if-not(#{[][1]}%)(loop[c % i 0](if(every? #{1 2}c)(if(=[2]c)i(recur(map count(partition-by + c))(inc i))))))

一个loop带有边缘情况的预检查的基础。返回nil无效输入。我不知道(= [2] '(2))true:o


1

Python 2,146个字节(仅功能)

f=lambda l,i=0:i if l==[1]else 0if max(l)>2or min(l)<1else f([len(x)+1for x in"".join(`v!=l[i+1]`[0]for i,v in enumerate(l[:-1])).split("T")],i+1)

在错误的输入上返回0(可以,因为它是1索引的)。像这样简单地使用它:

print(f([1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1]))

1

Mathematica,82个字节

FixedPointList[#/.{{2}->T,{(1|2)..}:>Length/@Split@#,_->0}&,#]~FirstPosition~T-1&

Function它会反复用{2}未定义的符号替换,并在下一次迭代中替换T(一个或多个)1s和2s 的列表,以及0直到达到固定点为止的其他任何值,然后在结果减号中返回FirstPosition该符号T的。输出是其中是(以达到所需的迭代-indexed)号码为truthy壳体和FixedPointList1{n}n1{2}-1+Missing["NotFound"]为falsy情况。

如果输出必须是n而不是{n},则将花费另外三个字节:

Position[FixedPointList[#/.{{2}->T,{(1|2)..}:>Length/@Split@#,_->0}&,#],T][[1,1]]-1&

1

Python 2中184个163 156字节

  • @Felipe Nardi Batista保存了21个字节!!!! 非常感谢!!!!
  • Halvard Hummel保存了7个字节!谢谢

Python 2,156个字节

a,c=input(),0
t=a==[]
while 1<len(a)and~-t:
 r,i=[],0
 while i<len(a):
	j=i
	while[a[j]]==a[i:i+1]:i+=1
	r+=[i-j]
 a=r;c+=1;t=any(x>2for x in a)
print~c*t+c

在线尝试!

说明:

a,c=input(),0                             #input and initialize main-counter 

t=a==[]                                   #set t to 1 if list's empty. 

while len(a)>1:                           #loop until list's length is 1.

 r,i=[],0                                 #Initialize temp. list and 
                                          #list-element-pointer 

 while i<len(a):                          #loop for the element in list 

  j=0                                     #set consecutive-item-counter to 0   

  while(i+j)<len(a)and a[i]==a[i+j]:j+=1  #increase the consec.-counter

  r+=[j];i+=j                             #add the value to a list, move the 
                                          #list-element-pointer 

 a=r;c+=1;t=any(x>2for x in a)            #update the main list, increase t 
                                          #the counter, check if any number 
 if t:break;                              #exceeds 2 (if yes, exit the loop)

print[c,-1][t]                            #print -1 if t or else the 
                                          #counter's 
                                          #value 



1

Python 2,122字节

def f(s,c=2,j=0):
 w=[1]
 for i in s[1:]:w+=[1]*(i!=s[j]);w[-1]+=i==s[j];j+=1
 return(w==[2])*c-({1,2}!=set(s))or f(w,c+1)

在线尝试!

Python 3,120字节

def f(s,c=2,j=0):
 w=[1]
 for i in s[1:]:w+=[1]*(i!=s[j]);w[-1]+=i==s[j];j+=1
 return(w==[2])*c-({1,2}!={*s})or f(w,c+1)

在线尝试!

说明

初始化一个新的序列(w),以存储还原的下一个迭代。初始化一个计数器(c)以跟踪迭代次数。

将原始序列中的每个项目与先前的值进行比较。如果它们相同,则将(w)的最后一项的值加1。如果它们不同,则将序列(w)扩展为[1]。

如果w == [2],则返回计数器(c)。否则,如果原始序列包含1和2以外的其他项目,则返回值-1。如果两者都不是,则以新序列(w)作为(s)递归调用该函数,并将计数器(c)递增1。


为了节省一个字节,我尝试将前两行合并为def f(s,c=2,j=0,w=[1]):,但这给出了不同的结果。有人可以解释为什么吗?
吉斯


@JoKing完全有道理,谢谢!
吉特

0

R,122字节

a=scan()
i=0
f=function(x)if(!all(x%in%c(1,2)))stop()
while(length(a)>1){f(a)
a=rle(a)$l
f(a)
i=i+1}
if(a==2)i else stop()

通过所有测试用例。否则引发一个或多个错误。我讨厌有效性检查;如果输入很好,那么此代码本来可以适用;即使输入是1和2的序列(不一定是Kolakoski序列的前缀),它也会更短。在这里,我们必须检查初始向量(否则[-2,1]将通过测试用例)和结果向量(否则[1,1,1]将通过)。


0

红宝石81 77字节

f=->a,i=1{a[1]&&a-[1,2]==[]?f[a.chunk{|x|x}.map{|x,y|y.size},i+1]:a==[2]?i:0}

在线尝试!

编辑:通过转换为递归lambda保存了4个字节。

返回1索引的迭代数或0作为falsey。

利用了Ruby枚举(enumerable)的块方法,该方法恰好满足了我们的需要-将相同编号的连续运行分组在一起。行程的长度构成了下一次迭代的数组。在数组长于1个元素且未遇到1和2以外的数字时保持迭代。


0

Pyth,45个字节

L?||qb]1!lb-{b,1 2_1?q]2b1Z.V0IKy~QhMrQ8*KhbB

在线尝试!

这可能仍然可以打高尔夫球。如果.?按照我希望的方式工作,那肯定是可以打高尔夫球的(是else最里面的结构而不是最外面的结构)

L?||qb]1!lb-{b,1 2_1?q]2b1Z # A lambda function for testing an iteration of the shortening
L                           # y=lambda b:
 ?                          # if
    qb]1                    #    b == [1]
   |    !lb                 #      or !len(b)
  |         {b              #        or b.deduplicate()
           -  ,1 2          #             .difference([1,2]):
                  _1        #               return -1
                    ?q]2b1Z # else: return 1 if [2] == b else Z (=0)

.V0                         # for b in range(0,infinity):
   IKy~Q                    # if K:=y(Q :=        (applies y to old value of Q)
        hM                  #    map(_[0],
          rQ8               #               run_length_encode(Q)):
             *Khb           #    print(K*(b+1))
                 B          #    break

0

Perl -p 5,71个字节

$_.=$";s/(. )\1*/$&=~y|12||.$"/ge&$.++while/^([12] ){2,}$/;$_=/^2 $/*$.

在线尝试!

1-索引。输出0错误。

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.