Riduzione di Kolakoski


27

Panoramica

Alcuni di voi potrebbero essere a conoscenza della sequenza di Kolakoski ( A000002 ), una sequenza autoreferenziale ben nota che ha le seguenti proprietà:

La proprietà coolio Kolakoski, yo.

È una sequenza contenente solo 1 e 2, e per ogni gruppo di 1 e due, se sommi la lunghezza delle corse, è uguale a se stesso, solo la metà della lunghezza. In altre parole, la sequenza di Kolakoski descrive la lunghezza delle corse nella sequenza stessa. È l'unica sequenza che lo fa ad eccezione della stessa sequenza con 1 iniziale cancellato. (Questo è vero solo se ti limiti alle sequenze composte da 1 e 2 secondi - Martin Ender)


La sfida

La sfida è, dato un elenco di numeri interi:

  • Output -1se l'elenco NON è un prefisso funzionante della sequenza di Kolakoski.
  • Emette il numero di iterazioni prima che la sequenza diventi [2].

L'esempio elaborato

Usando l'immagine fornita come esempio:

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

Pertanto, il numero risultante è 8per un input di [1,2,2,1,1,2,1,2,2,1,2,2,1,1,2,1,1].

9 va bene anche se stai indicizzando 1.


La suite di test (puoi testare anche con iterazioni secondarie)

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

Se sei confuso:

Verità: alla fine raggiungerà due senza alcun passaggio intermedio con elementi diversi da 1e 2. -Einkorn Enchanter 20 hours ago

Falsy: il valore finale non lo è [2]. I termini intermedi contengono qualcosa di diverso da qualcosa dell'insieme [1,2]. Un altro paio di cose, vedi esempi.


Questo è , il conteggio di byte più basso sarà il vincitore.


7
Possiamo usare qualsiasi valore di falso invece che solo -1?
mbomb007,

1
Cosa intendi con "NON un prefisso funzionante della sequenza di Kolakoski"? Avevo supposto che intendevi che l'elenco non raggiungesse alla fine [2]finché non avessi visto il [2,2,1,1,2,1,2]caso di test.
ngenisis,

1
@ngenisis Alla fine ne raggiungerà due senza alcun passaggio intermedio con elementi diversi da 1e 2.
Wheat Wizard

2
Potrebbe essere una buona idea aggiungere [1]come caso di prova.
Emigna,

1
@ mbomb007 qualsiasi valore distinto va bene. Un numero intero positivo non va bene. Se stai indicizzando 1 va bene. "Falso" va bene. L'errore va bene. Qualsiasi valore di ritorno non positivo va bene, anche -129.42910.
Magic Octopus Urn,

Risposte:


8

Haskell , 126 87 79 76 75 byte

39 byte salvati grazie a Ørjan Johansen

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

Provalo online!

Questo errore su input errato.


f(e di conseguenza !) può essere abbreviato molto usando la produzione pigra + span/ lengthinvece degli accumulatori. Provalo online!
Ørjan Johansen,

1
Sembra entrare in un ciclo infinito per[1]
Emigna,

1
@Emigna Darn. Mi costa 6 byte per risolverlo, ma l'ho risolto.
Mago del grano,

@ ØrjanJohansen Sembra un buon consiglio, ma non sono abbastanza abile in Haskell per capire cosa sta succedendo lì. Se vuoi, puoi pubblicarlo come risposta, ma almeno finché non so come funziona la tua soluzione, non lo aggiungerò alla mia risposta. :)
Wheat Wizard

1
Poi ho capito che questo è un caso in cui l'importazione è in realtà più breve (e anche più semplice da capire): import Data.List;f l=length<$>group l. ( <$>è sinonimo di mapqui.) Inoltre, invece di avere due -1casi diversi , è più breve usare un @(_:_:_)modello per forzare il caso principale a far corrispondere solo la lunghezza> = 2 liste. Provalo online!
Ørjan Johansen,

6

05AB1E , 22 byte

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

Provalo online!

Spiegazione

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

Non riesce[1,1,2,2,1,2,1,1,2,2,1,2,2,1,1,2,1,1]
Weijun Zhou

@WeijunZhou: Grazie, risolto!
Emigna,

Potresti aver dimenticato di aggiornare il link ...
Weijun Zhou

1
@WeijunZhou: Davvero l'ho fatto. Grazie ancora :)
Emigna il

3

SCALA, 290 (282?) Caratteri, 290 (282?) Byte

Mi ci è voluto così tanto ... Ma finalmente ho finito!

con questo codice:

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

Non so se dovrei contare i var u=tbyte, considerando che non uso tdurante l'algoritmo (la copia è solo per ottenere un modificabile varinvece del parametro tconsiderato come val- grazie ScaLa ). Per favore, dimmi se dovrei contarlo.

Abbastanza difficile. Provalo online!

PS: Stavo pensando di farlo in modo ricorsivo, ma dovrò passare un contatore come parametro della "sottofunzione" ricorsiva vera; questo fatto mi fa dichiarare due funzioni e questi caratteri / byte non sono altro che persi.

EDIT: Ho dovuto cambiare (?) Perché non siamo sicuri che dovremmo prendere in considerazione il [1]caso. Quindi ecco il codice modificato:

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

Non è ottimizzato (ho un duplicato "out" per le stesse condizioni: quando arrivo [2]e quando param [2]viene trattato separatamente).

NUOVO COSTO = 342 (Non ho modificato il titolo di proposito)


1
Sembra entrare in un ciclo infinito per[1]
Emigna,

Sì, ma come detto dall'OP (come ho capito almeno): "con l'iniziale 1 cancellato" e "Emetti il ​​numero di iterazioni prima che la sequenza diventi [2]"
V. Courtois,

A quanto ho capito, [1]non arriva mai [2]e dovrebbe quindi restituire -1 .
Emigna,

Vedo. Quindi pensi che dovrei mettere una condizione litte all'inizio? Grazie per il tuo consiglio.
V. Courtois,

Non conosco scala ma presumo che tu possa semplicemente modificare il loop per fermarlo quando la lunghezza della lista è inferiore a 2. Sembra che tu abbia già il controllo che l'elemento sia 2 alla fine.
Emigna,

2

JavaScript, 146 142 byte

Primo tentativo nel golf di codice, sembra che il "ritorno" nella funzione più grande sia abbastanza noioso ...

Inoltre, il controllo di b = 1 e b = 2 occupa alcuni byte ...

Ecco il codice:

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}

Spiegazione

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

Dati di test (utilizzando i dati di test forniti)

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]

Modifica 1: 146 -> 142: Revoca della mia modifica per ridurre i byte, poiché ciò influisce sull'output; e qualche modifica sull'ultima affermazione


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}salva 5 byte (per loop anziché while; virgole contro parentesi graffe; && vs if). Puoi utilizzare il compilatore di chiusura di google ( closing-compiler.appspot.com ) per ottenere queste ottimizzazioni fatte per te
Oki,

2

Gelatina ,26 25 22 21 20 byte

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

Provalo online!

Questo codice in realtà non funzionava correttamente fino a 20 byte e non me ne sono nemmeno accorto; stava fallendo sul [2,2]test case. Dovrebbe funzionare perfettamente ora.


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-indicizzati. Genera "ReferenceError: X is not defined"e "InternalError: too much recursion"su input errato.

Casi test


1

Clojure, 110 byte

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

Una base loopcon un controllo preliminare sui casi limite. Restituisce nilper input non validi. Non sapevo (= [2] '(2))è true: o


1

Python 2, 146 byte (solo funzione)

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)

Restituisce 0 sull'input falsy (ok poiché è 1-indicizzato). Usalo semplicemente in questo modo:

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

1

Mathematica, 82 byte

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

Functionche sostituisce più volte {2}con il simbolo non definito T, un elenco di (uno o più) 1s e 2s con l'iterazione successiva, e qualsiasi altra cosa con 0fino a raggiungere un punto fisso, quindi restituisce il FirstPositiondel simbolo Tnella risultante FixedPointListmeno 1. L'output è {n}dove nè il 1numero ( -indexed) di iterazioni necessarie per raggiungere {2}il caso di verità e -1+Missing["NotFound"]il caso di falsa.

Se l'output deve essere npiuttosto che {n}, costa altri tre byte:

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

1

Python 2 , 184 163 156 byte

  • @Felipe Nardi Batista ha salvato 21 byte !!!! molte grazie!!!!
  • Halvard Hummel ha salvato 7 byte !! Grazie

Python 2 , 156 byte

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

Provalo online!

Spiegazione:

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 byte

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)

Provalo online!

Python 3 , 120 byte

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)

Provalo online!

Spiegazione

Una nuova sequenza (w) viene inizializzata per memorizzare la successiva iterazione della riduzione. Un contatore (c) viene inizializzato per tenere traccia del numero di iterazioni.

Ogni elemento nelle sequenze originali viene confrontato con il valore precedente. Se sono uguali, il valore dell'ultimo elemento di (w) viene aumentato di 1. Se sono diversi, la sequenza (w) viene estesa con [1].

Se w == [2], viene restituito il contatore (c). Altrimenti, se la sequenza o le sequenze originali contengono elementi diversi da 1 e 2, viene restituito un valore -1. In caso contrario, la funzione viene chiamata in modo ricorsivo con la nuova sequenza (w) come (s) e il contatore (c) aumentato di 1.


Per salvare un byte, sto provando a combinare le prime due righe in def f(s,c=2,j=0,w=[1]):, ma questo dà un risultato diverso. Qualcuno potrebbe spiegare perché è così?
Jitse,


@JoKing Questo ha perfettamente senso, grazie!
Jitse,

0

R, 122 byte

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

Supera tutti i casi di test. In caso contrario genera uno o più errori. Odio i controlli di validità; questo codice avrebbe potuto essere giocato così bene se gli input fossero stati buoni; sarebbe più breve anche nel caso in cui l'input fosse una sequenza di 1 e 2, non necessariamente un prefisso della sequenza di Kolakoski. Qui, dobbiamo controllare sia il vettore iniziale (altrimenti il ​​caso di test [-2,1]) sarebbe passato) sia il vettore risultante (altrimenti [1,1,1]sarebbe passato).


0

Rubino , 81 77 byte

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}

Provalo online!

Modifica: salvato 4 byte convertendo in lambda ricorsiva.

Restituisce 1 numero indicizzato di iterazioni o 0 come false.

Fa uso del metodo chunk di Ruby enumerable, che fa esattamente ciò di cui abbiamo bisogno - raggruppando esecuzioni consecutive di numeri identici. Le lunghezze delle esecuzioni costituiscono l'array per la successiva iterazione. Mantiene l'iterazione mentre l'array è più lungo di 1 elemento e non sono stati rilevati numeri diversi da 1 e 2.


0

Pyth , 45 byte

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

Provalo online!

Questo è probabilmente ancora golfabile. È sicuramente golfabile se ha .?funzionato nel modo in cui speravo (essendo una elsestruttura più interna anziché più esterna)

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.