Kolakoski Azaltma


27

genel bakış

Bazılarınız , aşağıdaki özelliğe sahip kendi kendine referans dizisi olan Kolakoski Dizisinin ( A000002 ) farkında olabilir :

Coolio Kolakoski özelliği, yo.

Sadece 1'ler ve 2'ler içeren bir dizidir ve her bir 1 ve iki grup için, eğer çalışmaların uzunluğunu eklerseniz, uzunluk yalnızca yarısına eşittir. Başka bir deyişle, Kolakoski dizisi, dizinin kendisindeki işlemlerin uzunluğunu tarif eder. Silinen ilk 1 ile aynı dizi dışında bunu yapan tek dizidir. (Bu, yalnızca kendinizi 1s ve 2s'den oluşan dizilerle sınırlarsanız geçerlidir - Martin Ender)


Meydan okuma

Zorluk, tam sayıların bir listesi halinde verilir:

  • Çıktı -1liste Kolakoski dizisinin bir çalışma öneki DEĞİL ise.
  • Dizi oluşmadan önce yineleme sayısını yazınız [2].

Çalışılan Örnek

Sağlanan görüntüyü örnek olarak kullanma:

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

Bu nedenle, sonuç numarası 8bir giriş içindir [1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1].

9 1 indeksleme yapıyorsanız da iyidir.


Test Paketi (Alt yinelemelerle de test edebilirsiniz)

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

Kafanız karıştıysa:

Hakikat: Sonunda 1ve dışında herhangi bir öğeye sahip olan herhangi bir ara adım olmadan ikiye ulaşacaktır 2. -Einkorn Enchanter 20 hours ago

Falsy: Bitiş değeri değil [2]. Ara terimler, kümeden başka bir şey içerir [1,2]. Birkaç başka şey, örneklere bakın.


Bu , en düşük bayt sayısı victor olacak.


7
Sadece bir falsey değeri kullanabilir miyiz -1?
mbomb007

1
"Kolakoski sekansının çalışma öneki DEĞİLDİR" ile ne demek istiyorsunuz? Test vakasını [2]görene kadar listenin sonunda ulaşamayacağını kastetmiştim [2,2,1,1,2,1,2].
ngenis,

1
@ ngenis Sonunda, 1ve dışında herhangi bir elemana sahip hiçbir ara adım olmadan iki taneye ulaşacaktır 2.
Buğday Sihirbazı,

2
[1]Test olayı olarak eklemek iyi bir fikir olabilir .
Emigna

1
@ mbomb007 herhangi bir belirgin değer iyi. Olumlu bir tamsayı iyi değil. 1 indeksleme yapıyorsanız 0 iyidir. "Yanlış" iyi. Hata yapmak iyi. Olumlu olmayan geri dönüş değerleri gayet iyi, -129.42910.
Magic Octopus Urn

Yanıtlar:


8

Haskell , 126 87 79 76 75 bayt

Ørjan Johansen sayesinde 39 bayt kurtarıldı

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

Çevrimiçi deneyin!

Bu hatalı girişte hatalar.


f(ve sonuç olarak !) , akümülatör yerine tembel üretim + span/ kullanarak bir çok kısaltılabilir length. Çevrimiçi deneyin!
Ørjan Johansen

1
İçin sonsuz bir döngüye girmek gibi görünüyor[1]
Emigna

1
@Emigna Darn. Bunu düzeltmek bana 6 bayta mal oldu, ama ben düzelttim.
Buğday Sihirbazı,

@ ØrjanJohansen İyi bir bahşiş gibi gözüküyor, ancak Haskell'de neler olup bittiğini anlayacak kadar yetkin değilim. İsterseniz kendi cevabınız olarak gönderebilirsiniz ancak en azından çözümünüzün nasıl çalıştığını bilmediğim sürece, cevabımı eklemeyecağım. :)
Buğday Sihirbazı,

1
Daha sonra bu bir ithalat aslında daha kısa (ve ayrıca daha basit anlamak için) olan bir durumdur fark: import Data.List;f l=length<$>group l. ( burada <$>eşanlamlıdır map.) Ayrıca, iki farklı duruma sahip olmak yerine , ana davayı yalnızca uzunluk>> 2 listeleriyle eşleşmeye zorlamak için -1bir @(_:_:_)kalıp kullanmak daha kısadır . Çevrimiçi deneyin!
Ørjan Johansen

6

05AB1E , 22 bayt

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

Çevrimiçi deneyin!

açıklama

[                        # 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

Başarısız[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]
Weijun Zhou

@WeijunZhou: Teşekkürler, sabit!
Emigna

Bağlantıyı güncellemeyi unutmuş olabilirsin ...
Weijun Zhou

1
@WeijunZhou: Gerçekten de vardı. Tekrar teşekkürler :)
Emigna

3

SCALA, 290 (282?) Karakter, 290 (282?) Bayt

Beni sooo loong aldı ... Ama sonunda bittim!

bu kodla:

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

Ben saymak gerekir eğer bilmiyorum var u=tbayt içine ben kullanmıyorum dikkate t(kopya sadece modifyable elde etmektir algoritma sırasında varyerine parametre tolarak kabul val- teşekkürler Scala ). Lütfen saymalı mıyım söyle.

Yeterince sert. Çevrimiçi deneyin!

PS: Özyinelemeyle yapmayı düşünüyordum, ancak gerçek özyinelemeli "alt işlev" in bir parametresi olarak bir sayacı geçmem gerekecek; bu durum iki işlevi ilan etmemi sağlıyor ve bu karakter / bayt kayıptan başka bir şey değil.

EDIT: Değişmek zorunda kaldım (?) Çünkü sayım [1]davasında almamız gerektiğinden emin değiliz . Yani burada değiştirilmiş kod:

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

Optimize edilmedi (aynı koşullar için yinelenen bir "çıkış" var: ne zaman gidiyorum [2]ve param [2]ayrı olarak ele alındığında).

NEW COST = 342 (Başlığı bilerek değiştirmedim)


1
İçin sonsuz bir döngüye girmek gibi görünüyor[1]
Emigna

Evet, ancak OP tarafından söylendiği gibi (en azından anladığım gibi): "ilk 1 silinmiş" ve "Dizi gerçekleşmeden önce yineleme sayısını yaz [2]"
V. Courtois

Anladığım kadarıyla, [1]asla ulaşmaz [2]ve -1'e geri dönmesi gerekir .
Emigna,

Anlıyorum. Sence başında bir litte şartı koymalı mıyım? Tavsiyeniz için teşekkürler.
V. Courtois,

Ölçek bilmiyorum ama listenin uzunluğu 2'den küçük olduğunda duracak döngüyü değiştirebildiğinizi farz ediyorum, zaten öğenin sonunda 2 olduğunu kontrol etmiş gibi görünüyorsunuz.
Emigna,

2

JavaScript, 146 142 bayt

İlk önce kod golfünü deneyin, daha büyük işlevdeki "dönüş" oldukça sıkıcı görünüyor.

Ayrıca, b = 1 ve b = 2'nin kontrolü bazı baytları alır ...

İşte kod:

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}

açıklama

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

Test verileri (verilen test verilerini kullanarak)

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]

Düzenleme 1: 146 -> 142: Baytı azaltma ile ilgili düzenlememi iptal et; ve son ifadede yapılan bazı düzenlemeler


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 bayt kaydeder (bir süre yerine döngü için; virgüllere karşı parantez; Bu optimizasyonları sizin için yapmak için google'ın kapanış derleyicisini ( closure-compiler.appspot.com ) kullanabilirsiniz
Oki

2

Jelly ,26 25 22 21 20 bayt

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

Çevrimiçi deneyin!

Bu kod aslında 20 byte'a kadar düzgün çalışmıyordu ve ben farkına bile varmadım; [2,2]Test davasında başarısız oldu . Şimdi mükemmel çalışması gerekir.


2

JavaScript (ES6), 127 126 95 80 bayt

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 endeksli. Atar "ReferenceError: X is not defined"ve "InternalError: too much recursion"kötü girdi.

Test durumları


1

Clojure, 110 bayt

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

loopKenar durumlarda ön kontrol ile temel . İade nilgeçersiz girişler için. Bilmiyordum (= [2] '(2))ki true: o


1

Python 2, 146 bayt (yalnızca işlev)

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)

Sahte girişte 0 değerini döndürür (tamam 1-dizinli olduğundan). Basitçe bu şekilde kullanın:

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

1

Mathematica, 82 bayt

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

Function{2}tanımlanmamış sembolle T, art arda değiştirilen sembolle , sonraki yinelemeyle (bir veya daha fazla) 1s ve 2s'nin bir listesi ve 0sabit bir noktaya ulaşılana kadar olan herhangi bir şey , daha sonra ortaya çıkan eksi FirstPositioniçindeki sembolün işaretini verir . Çıktı, ulaşmak için gereken ( -dexed) yineleme sayısının olduğu yerdirTFixedPointList1{n}n1{2} truthy durum için ve -1+Missing["NotFound"]falsy durum için.

Çıktının nyerine olması gerekiyorsa {n}, üç bayt maliyeti daha:

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

1

Python 2 , 184 163 156 bayt

  • @Felipe Nardi Batista 21 bayt kurtardı !!!! çok teşekkürler!!!!
  • Halvard Hummel 7 byte kurtardı! Teşekkürler

Python 2 , 156 bayt

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

Çevrimiçi deneyin!

Açıklama:

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 bayt

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)

Çevrimiçi deneyin!

Python 3 , 120 bayt

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)

Çevrimiçi deneyin!

açıklama

Azaltmanın bir sonraki yinelemesini saklamak için yeni bir dizi (w) başlatıldı. Yinelemelerin sayısını takip etmek için bir sayaç (c) çalıştırılır.

Orijinal dizilimdeki her öğe önceki değerle karşılaştırılır. Eğer aynılarsa, (w) 'nin son öğesinin değeri 1 ile artar. Farklılarsa, sıra (w) [1] ile uzatılır.

W == [2] ise, sayaç (c) döndürülür. Aksi takdirde, orijinal diziler 1 ve 2'den başka öğeler içeriyorsa, -1 değeri döndürülür. Durum böyle değilse, işlev (r) olarak yeni diziyle (w) tekrarlı olarak çağrılır ve sayaç (c) 1 artar.


Bir bayttan tasarruf etmek için ilk iki satırı birleştirmeye çalışıyorum def f(s,c=2,j=0,w=[1]):, ancak bu farklı bir sonuç veriyor. Bunun neden olduğunu açıklayan var mı?
Jitse


@JoKing Bu mükemmel, mantıklı geliyor!
Jitse

0

R, 122 bayt

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

Tüm test durumlarını geçer. Aksi takdirde bir veya daha fazla hata atar. Geçerlilik kontrollerinden nefret ediyorum; girişler güzel olsaydı bu kod çok golf olabilirdi; girişin Kolakoski dizisinin bir öneki değil, 1'lerin ve 2'lerin bir dizisi olması durumunda bile daha kısa olacaktır. Burada, hem ilk vektörü (aksi takdirde test durumu [-2,1]) geçtiğini kontrol etmeliyiz hem de sonuçtaki vektörü (aksi takdirde [1,1,1]geçecekti).


0

Ruby , 81 77 bayt

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}

Çevrimiçi deneyin!

Düzenleme: özyinelemeli lambda dönüştürerek 4 bayt kaydedildi.

1 indeksli yineleme sayısını veya 0 değerini falsey olarak döndürür.

Tam olarak ihtiyaç duyduğumuz şeyi yapan - aynı sayıdaki ardışık işlemleri birlikte gruplayan Ruby numaralandırılabilir öbek yöntemini kullanır. Çalışmaların uzunlukları bir sonraki yinelemenin dizisini oluşturur. Dizi 1 öğeden daha uzunken ve 1 ve 2'den başka sayılarla karşılaşılmadığında yinelemeyi sürdürür.


0

Pyth , 45 bayt

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

Çevrimiçi deneyin!

Bu muhtemelen hala golf oynamaktadır. Umduğum gibi .?çalıştıysanız kesinlikle golf oynamak mümkün ( elseen dıştaki en içteki yapı için)

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.