Kolakoski-Reduktion

27

Überblick

Einige von Ihnen kennen möglicherweise die Kolakoski-Sequenz ( A000002 ), eine bekannte selbstreferenzielle Sequenz mit der folgenden Eigenschaft:

Das coolio Kolakoski Eigentum, yo.

Es ist eine Sequenz, die nur Einsen und Zweien enthält, und für jede Gruppe von Einsen und Zweien entspricht sie sich selbst, wenn Sie die Länge der Läufe addieren, nur der halben Länge. Mit anderen Worten, die Kolakoski-Sequenz beschreibt die Länge der Läufe in der Sequenz selbst. Dies ist die einzige Sequenz, die dies ausführt, mit Ausnahme der gleichen Sequenz, bei der die erste 1 gelöscht wurde. (Dies gilt nur, wenn Sie sich auf Sequenzen aus 1s und 2s beschränken - Martin Ender)


Die Herausforderung

Die Herausforderung ist, eine Liste von ganzen Zahlen gegeben:

  • Ausgang , -1wenn die Liste keine Arbeits Präfix der Kolakoski Sequenz ist.
  • Geben Sie die Anzahl der Iterationen aus, bevor die Sequenz erstellt wird [2].

Das ausgearbeitete Beispiel

Verwenden Sie das bereitgestellte Bild als Beispiel:

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

Daher ist die resultierende Zahl 8für eine Eingabe von [1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1].

9 ist auch in Ordnung, wenn Sie 1-indizieren.


Die Test Suite (Sie können auch mit Unteriterationen testen)

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

Wenn Sie verwirrt sind:

Wahrheit: Irgendwann werden zwei erreicht, ohne dass ein Zwischenschritt andere Elemente als 1und enthält 2. -Einkorn Enchanter 20 hours ago

Falsy: Endwert ist nicht [2]. Zwischenbegriffe enthalten etwas anderes als etwas aus der Menge [1,2]. Ein paar andere Dinge, siehe Beispiele.


Dies ist , die niedrigste Byteanzahl ist der Sieger.

Magische Kraken-Urne
quelle
7
Können wir irgendeinen falschen Wert anstelle von nur verwenden -1?
mbomb007
1
Was meinst du mit "KEIN funktionierendes Präfix der Kolakoski-Sequenz"? Ich hatte angenommen, Sie meinten, die Liste würde irgendwann nicht mehr reichen, [2]bis ich den [2,2,1,1,2,1,2]Testfall gesehen habe.
Genisis
1
@ngenisis Es werden schließlich zwei erreicht, ohne dass ein Zwischenschritt andere Elemente als 1und enthält 2.
Weizen-Assistent
2
Könnte eine gute Idee sein, [1]als Testfall hinzuzufügen .
Emigna
1
@ mbomb007 Jeder eindeutige Wert ist in Ordnung. Eine positive ganze Zahl ist nicht in Ordnung. Wenn Sie 1-indizieren, ist 0 in Ordnung. "Falsch" ist in Ordnung. Fehler sind in Ordnung. Jeder nicht positive Rückgabewert ist in Ordnung, sogar -129.42910.
Magic Octopus Urn

Antworten:

8

Haskell , 126 87 79 76 75 Bytes

39 Bytes gespart dank Ørjan Johansen

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

Probieren Sie es online!

Dieser Fehler bei fehlerhafter Eingabe.

Weizen-Assistent
quelle
f(und damit !) kann eine Menge unter Verwendung lazy Produktion + verkürzt werden span/ lengthanstelle von Akkumulatoren. Probieren Sie es online!
Ørjan Johansen
1
Scheint eine Endlosschleife für[1]
Emigna
1
@Emigna Darn. Es kostet mich 6 Bytes, um es zu reparieren, aber ich habe es behoben.
Weizen-Assistent
@ ØrjanJohansen Das scheint ein guter Tipp zu sein, aber ich beherrsche Haskell nicht genug, um zu verstehen, was dort vor sich geht. Wenn Sie möchten, können Sie es als Ihre eigene Antwort veröffentlichen, aber ich werde es meiner Antwort nicht hinzufügen, solange ich nicht weiß, wie Ihre Lösung funktioniert. :)
Weizen-Assistent
1
Ich erkennen , dann ist dies ein Fall, in dem ein Import tatsächlich kürzer ist (und auch einfacher zu verstehen): import Data.List;f l=length<$>group l. ( <$>ist ein Synonym für maphier.) Anstatt zwei verschiedene -1Fälle zu haben, ist es auch kürzer, ein @(_:_:_)Muster zu verwenden, um zu erzwingen, dass der Hauptfall nur mit der Länge> = 2 Listen übereinstimmt. Probieren Sie es online!
Ørjan Johansen
6

05AB1E , 22 Bytes

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

Probieren Sie es online!

Erläuterung

[                        # 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
Emigna
quelle
Scheitert an[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]
Weijun Zhou
@ WeijunZhou: Danke, behoben!
Emigna
Sie haben möglicherweise vergessen, den Link zu aktualisieren ...
Weijun Zhou
1
@ WeijunZhou: In der Tat hatte ich.
Nochmals vielen
3

SCALA, 290 (282?) Zeichen, 290 (282?) Bytes

Es hat mich sooo lang gekostet ... aber ich bin endlich fertig!

mit diesem Code:

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

Ich weiß nicht, ob ich das var u=tin die Bytes zählen soll, wenn ich tbedenke , dass ich es nicht während des Algorithmus verwende (die Kopie dient nur dazu, varanstelle des Parameters t, der als val- danke ScaLa - betrachtet wird, ein änderbares zu erhalten ). Bitte sag mir, ob ich es zählen soll.

Hart genug. Probieren Sie es online!

PS: Ich habe darüber nachgedacht, es rekursiv zu machen, aber ich muss einen Zähler als Parameter der rekursiven "Unterfunktion" übergeben. Diese Tatsache veranlasst mich, zwei Funktionen zu deklarieren, und diese Zeichen / Bytes sind nichts als verloren.

EDIT: Ich musste ändern (?), Weil wir nicht sicher sind, ob wir den [1]Fall berücksichtigen sollen . Also hier ist der geänderte Code:

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

Es ist nicht optimiert (ich habe ein Duplikat "out" für die gleichen Bedingungen: wenn ich [2]ankomme und wenn param [2]getrennt behandelt wird).

NEW COST = 342 (Ich habe den Titel nicht absichtlich geändert)

V. Courtois
quelle
1
Scheint, eine Endlosschleife für[1]
Emigna
Ja, aber wie vom OP gesagt (wie ich zumindest verstanden habe): "Mit der ersten 1 gelöscht" und "Die Anzahl der Iterationen [2]
V. Courtois
Erreicht meines Erachtens [1]niemals [2]und sollte daher -1 zurückgeben .
Emigna
Aha. Meinst du, ich sollte eine kleine Bedingung an den Start stellen? Danke für deinen Rat.
V. Courtois
Ich kenne Scala nicht, aber ich gehe davon aus, dass Sie die Schleife so ändern können, dass sie stoppt, wenn die Länge der Liste kleiner als 2 ist. Sie scheinen bereits zu prüfen, ob das Element am Ende 2 ist.
Emigna
2

JavaScript, 146 142 Bytes

Beim ersten Versuch mit Code-Golf scheint es, dass das "Zurück" in der größeren Funktion ziemlich mühsam ist ...

Auch die Überprüfung von b = 1 und b = 2 nimmt einige Bytes in Anspruch ...

Hier ist der Code:

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}

Erläuterung

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

Testdaten (unter Verwendung der angegebenen Testdaten)

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]

Edit 1: 146 -> 142: Widerruf meiner Bearbeitung beim Reduzieren von Bytes, da dies die Ausgabe beeinflusst; und einige Änderungen an der letzten Anweisung

user71543
quelle
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}Speichert 5 Bytes (for-Schleife statt while; Kommas vs geschweifte Klammern; && vs if). Sie können den Closure Compiler von Google ( closure-compiler.appspot.com ) verwenden, um diese Optimierungen für Sie durchzuführen
Oki,
2

Gelee ,26 25 22 21 20 Bytes

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

Probieren Sie es online!

Dieser Code funktionierte erst mit 20 Bytes richtig und ich bemerkte es nicht einmal. es ist im [2,2]Testfall fehlgeschlagen . Sollte jetzt perfekt funktionieren.

streuen
quelle
2

JavaScript (ES6), 127 126 95 80 Byte

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-indiziert. Wirft "ReferenceError: X is not defined"und "InternalError: too much recursion"auf schlechte Eingabe.

Testfälle

Oki
quelle
1

Clojure, 110 Bytes

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

Ein Basic loopmit einer Vorabprüfung von Randfällen. Gibt nilfür ungültige Eingaben zurück. Ich wusste nicht, (= [2] '(2))ist true: o

NikoNyrh
quelle
1

Python 2, 146 Bytes (nur Funktion)

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)

Gibt bei einer falschen Eingabe 0 zurück (ok, da 1-indiziert). Benutze es einfach so:

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

Mathematica, 82 Bytes

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

Functiondie wiederholt {2}durch das undefinierte Symbol T, eine Liste von (einem oder mehreren) 1s und 2s mit der nächsten Iteration und alles andere mit, 0bis ein fester Punkt erreicht ist, ersetzt, dann gibt die FirstPositiondes Symbols Tim resultierenden FixedPointListMinus zurück 1. Ausgabe ist, {n}wo ndie ( 1-indexierte) Anzahl von Iterationen ist, die benötigt werden, um {2}nach dem Wahrheitsfall und -1+Missing["NotFound"]dem Falschfall zu suchen.

Wenn die Ausgabe neher als sein muss {n}, kostet es drei weitere Bytes:

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

Python 2 , 184 163 156 Bytes

  • @Felipe Nardi Batista hat 21 Bytes gespart !!!! Vielen Dank!!!!
  • Halvard Hummel hat 7 Bytes gespart !! Vielen Dank

Python 2 , 156 Bytes

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

Probieren Sie es online!

Erläuterung:

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 
officialaimm
quelle
1
156 Bytes
Halvard Hummel
1

Python 2 , 122 Bytes

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)

Probieren Sie es online!

Python 3 , 120 Bytes

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)

Probieren Sie es online!

Erläuterung

Eine neue Sequenz (w) wird initialisiert, um die nächste Iteration der Reduktion zu speichern. Ein Zähler (c) wird initialisiert, um die Anzahl der Iterationen zu verfolgen.

Jedes Element in der Originalsequenz (den Originalsequenzen) wird mit dem vorherigen Wert verglichen. Wenn sie gleich sind, wird der Wert des letzten Elements von (w) um 1 erhöht. Wenn sie unterschiedlich sind, wird die Sequenz (w) um [1] erweitert.

Wenn w == [2] ist, wird der Zähler (c) zurückgegeben. Wenn die ursprüngliche (n) Sequenz (en) andere Elemente als 1 und 2 enthält, wird ein Wert von -1 zurückgegeben. Ist dies nicht der Fall, wird die Funktion rekursiv mit der neuen Folge (w) als (s) aufgerufen und der Zähler (c) um 1 erhöht.

Jitse
quelle
Um ein Byte zu speichern, versuche ich, die ersten beiden Zeilen zu kombinieren def f(s,c=2,j=0,w=[1]):, aber das ergibt ein anderes Ergebnis. Kann jemand erklären, warum das so ist?
Jitse
@JoKing Das macht Sinn, danke!
Jitse
0

R, 122 Bytes

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

Besteht alle Testfälle. Löst ansonsten einen oder mehrere Fehler aus. Ich hasse Gültigkeitsprüfungen. Dieser Code hätte so gut gespielt werden können, wenn die Eingaben nett gewesen wären. Es wäre kürzer, selbst wenn die Eingabe eine Folge von 1 und 2 wäre, nicht notwendigerweise ein Präfix der Kolakoski-Folge. Hier müssen wir überprüfen, ob sowohl der Anfangsvektor (sonst wäre der Testfall [-2,1]bestanden) als auch der resultierende Vektor (sonst [1,1,1]wäre bestanden).

Andreï Kostyrka
quelle
0

Ruby , 81.77 Bytes

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}

Probieren Sie es online!

Bearbeiten: 4 Bytes durch Konvertieren in rekursives Lambda gespeichert.

Gibt 1-indizierte Anzahl von Iterationen oder 0 als Falsey zurück.

Verwendet die Chunk-Methode von Ruby Enumerable, die genau das tut, was wir brauchen - sie gruppiert aufeinanderfolgende Läufe mit identischen Zahlen. Die Längen der Läufe bilden das Array für die nächste Iteration. Die Iteration wird fortgesetzt, solange das Array länger als 1 Element ist und keine anderen Zahlen als 1 und 2 gefunden wurden.

Kirill L.
quelle
0

Pyth , 45 Bytes

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

Probieren Sie es online!

Das ist wohl noch golfen. Es ist definitiv golfen, wenn es so .?funktioniert, wie ich es mir erhofft hatte (es ist eine elseStruktur für das Innerste anstatt für das Äußerste)

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
ar4093
quelle
0

Perl 5 -p , 71 Bytes

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

Probieren Sie es online!

1-indexiert. Ausgaben 0für falsy.

Xcali
quelle