Drop of Chaos (Costruire una sequenza minimamente aperiodica)


9

L'idea qui è quella di produrre un modello quasi ripetitivo. Cioè, la sequenza che si sta costruendo cambia all'ultimo momento per evitare una ripetizione di qualche sottosequenza. Le conseguenze del tipo AA e ABA devono essere evitate (dove B non è più lungo di A).

Esempi:

Vado avanti e inizierò elencando tutti i piccoli esempi per rendere più chiara la mia descrizione. Cominciamo con 0.

Valido: 0

Non valido: 00 (modello AA)
Valido: 01

Non valido: 010 (modello ABA)
Non valido: 011 (modello AA)
Valido: 012

Valido: 0120
Non valido: 0121 (modello ABA)
Non valido: 0122 (modello AA)

Non valido: 01200 (modello AA)
Non valido: 01201 (modello ABA; 01-2-01)
Non valido: 01202 (modello ABA)
Valido: 01203

Ora, credo fermamente che a 4non sia mai necessario, anche se non ne ho una prova, perché ho trovato facilmente sequenze di centinaia di caratteri che usano solo 0123. (Probabilmente è strettamente correlato al modo in cui sono necessari solo tre caratteri per avere stringhe infinite che non hanno alcun modello AA. C'è una pagina Wikipedia su questo.)

Input Output

L'input è un numero intero singolo, positivo, diverso da zero n. Si può presumere che n <= 1000.

L'output è una nsequenza di caratteri senza sottosequenze che corrispondono a uno schema proibito (AA o ABA).

Ingressi e uscite di esempio

>>> 1
0

>>> 2
01

>>> 3
012

>>> 4
0120

>>> 5
01203

>>> 50
01203102130123103201302103120132102301203102132012

Regole

  • Sono 0123ammessi solo i personaggi .
  • B non è più di A. Questo per evitare la situazione in cui 012345deve essere seguita da 6perché 0123451ha questo: 1-2345-1. In altre parole, la sequenza sarebbe banale e poco interessante.
  • npuò essere immesso attraverso qualsiasi metodo desiderato, ad eccezione della codifica hardware.
  • L'output può essere un elenco o una stringa, a seconda di quale è più semplice.
  • Nessuna forza bruta ; il tempo di esecuzione dovrebbe essere dell'ordine dei minuti, al massimo un'ora su una macchina molto lenta, per n=1000. (Questo ha lo scopo di squalificare le soluzioni che attraversano semplicemente tutte le npermutazioni di lunghezza {0,1,2,3}, in modo tale che i trucchi e i trucchi simili siano vietati.)
  • Le scappatoie standard non sono consentite, come al solito.
  • Il punteggio è in byte. Si tratta di , quindi vince l'ingresso più breve (probabilmente - vedi bonus).
  • Bonus: seleziona la cifra più bassa consentita ad ogni passaggio. Se 1e 3sono possibili scelte per la cifra successiva nella sequenza, selezionare 1. Sottrai 5 byte dal tuo punteggio. Tuttavia, prendere nota della nota seguente.

Nota!

I vicoli ciechi sono possibili. Il tuo programma o funzione deve evitare questi. Ecco un esempio:

Ceppo: 01203102130123103201302103120132102301203102132012302103120130231032012302132031023012032102312013021031230132031021301203210230132031023
Ceppo: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301323013023
Ceppo: 0120310213012310320130210312013210230120310213201230210312013023103201230213203102301203210231201302103123013203102130120321023013203123022032102301
Ceppo: 012031021301231032013021031201321023012031021320123021031201302310320123021320310230120321023120130210312301320310213012032102301332013023

Ognuna di queste sequenze non può essere estesa ulteriormente (senza usare a 4). Ma nota anche che c'è una differenza cruciale tra i primi due e i secondi due. Sostituirò la sottosequenza iniziale condivisa con una Xper renderlo più chiaro.

Ceppo: X2130120
Ceppo: X2130123
Ceppo: X320
Ceppo: X321301203102130

Le ultime due cifre di Xsono 10, quindi le uniche scelte possibili per la cifra successiva sono 2e 3. La scelta 2porta a una situazione in cui la sequenza deve terminare. L'algoritmo goloso non funzionerà qui. (Non senza backtracking, comunque.)


Si può usare una strategia di forza bruta per testare ogni possibile stringa, anche se non darà un risultato in tempo realistico? Sai che ci sarà una soluzione per tutti n? Se qualcuno fornisce un algoritmo euristico semi-avido, come verificherai che non si verifichino problemi per un periodo molto lungo? Il problema generale è interessante e non sono stato in grado di trovare nulla sull'evitamento del motivo in cui limitiamo la lunghezza di parte del motivo. Se qualcuno può produrre una ricetta generale, mi aspetto che sia l'approccio migliore.
xnor

Credo di non aver consentito la forza bruta nelle regole. Dovrei probabilmente evidenziarlo. Non ho la prova che esista una soluzione per tutti n, ma dato che i ceppi che il mio programma trova tendono ad allungarsi di una media di 10 cifre ogni volta, sono sicuro che esista una sequenza infinita. Non sono sicuro di come un algoritmo semi-avido possa essere testato per sequenze arbitrariamente grandi. Potrei limitare il requisito a n= 1000 e semplicemente non preoccuparmi di un livello superiore n.
El'endia Starman,

4
Suppongo AAsia davvero il tipo ABAdove Bè vuoto. Questo potrebbe forse aiutare a semplificare alcune soluzioni.
Mathmandan,

Risposte:


6

Retina , 86 byte - 5 = 81

$
_
(r`^(?<-2>.)+_((.)+)\b$
$1!
\b$
0
3#
#
0#
1
1#
2
2#
3
)r`\1(?<-2>.)*((.)+)$
$0#
!
<empty>

Dove <empty>rappresenta una riga finale vuota. È possibile eseguire il codice sopra da un singolo file con il -sflag.

L'input dovrebbe essere dato all'unario , ad es 111111. Non ho ancora testato l'output nell'ordine di migliaia - due dei regex potrebbero rallentare un po 'dopo un po' - ma può facilmente gestire un paio di centinaia in pochi secondi.

Spiegazione

Questa è una semplice soluzione di backtracking.

  1. Aggiungi a 0.
  2. Mentre la sequenza corrente non è valida, rimuovi tutti i 3 finali e incrementa l'ultimo non 3.
  3. Ripeti fino a quando non abbiamo una sequenza valida della lunghezza desiderata.

Questo backtracking è implementato da un ciclo di sostituzioni regex che si interrompe quando la stringa rimane invariata attraverso una iterazione.

$
_

Questo aggiunge un _input, che viene utilizzato per separare l'input unario dalla sequenza che stiamo costruendo.

(r`^(?<-2>.)+_((.)+)\b$
$1!

Questa è la prima sostituzione nel loop (indicata dal primo (). La regex corrisponde se a) c'è un carattere di parola (cioè una cifra) alla fine della stringa (il che significa che la stringa è valida - vedremo di seguito che le sequenze non valide sono contrassegnate con un trailing #) e b) ci sono almeno tanti caratteri nella sequenza quanti nell'input (questo viene verificato usando i gruppi di bilanciamento ). In tal caso, rimuoviamo l'input e aggiungiamo a !. Questo !serve a far fallire tutte le regex nel loop, in modo tale da terminare.

\b$
0

Se alla fine è presente un carattere di parola (ovvero la sequenza è valida e il ciclo non è stato terminato dal passaggio precedente), aggiungere a 0.

3#
#

Se (invece) la sequenza era stata contrassegnata come non valida e terminata 3, la rimuoviamo 3(ma la sequenza rimane invalida, poiché non è possibile la continuazione per il prefisso corrente ... quindi anche il carattere successivo deve essere retrocesso).

0#
1
1#
2
2#
3

Se la sequenza è contrassegnata come non valida e qualsiasi cifra diversa da quella 3alla fine, incrementiamo la cifra e rimuoviamo l'indicatore.

)r`\1(?<-2>.)*((.)+)$
$0#

L'ultima sostituzione nel loop (come indicato dal )). Verifica se la stringa termina ABA(dove Bnon è più lungo Ama potenzialmente vuoto). Le lunghezze relative di Ae Bvengono nuovamente verificate utilizzando i gruppi di bilanciamento e la ripetizione di Aviene verificata con un semplice riferimento.

Se questa regex corrisponde, contrassegniamo la sequenza non valida aggiungendo #.

!
<empty>

Una volta terminato il loop, tutto ciò che dobbiamo fare è rimuovere !e vengono quindi lasciati con l'output desiderato.


2

Python 2, 175-5 = 170 byte

n=input();s='';u=j=-1
while n>len(s):
 while u>2:u=int(s[0]);s=s[1:]
 u+=1;t=`u`+s;m=c=0
 while t[c:]*0**m:c+=1;i=t[c:].find(t[:c]);m=j<i<=c
 if c>=len(t):s=t;u=j
print s[::j]

Questo è l'algoritmo goloso con backtracking. Vorrei che fosse più corto. Spero sia corretto (vedi sotto).

Costruisce la stringa di una cifra alla volta. Data una stringa di dcifre che ha già trovato, prova ad aggiungere a 0come la (d+1)cifra di st. Se non funziona, prova a 1, quindi a 2, quindi a 3. Se nessuna di queste funzioni, torna alla dcifra th e la incrementa (se inferiore a 3) o la rimuove (se uguale a 3, nel qual caso incrementa la precedente, ecc.).

Il controllo per la validità è la linea con .findin esso. Nel caso in cui qualcuno decida di leggere il mio codice, dovrei dire che questo programma sta effettivamente memorizzando la stringa al contrario, il che significa che sta aggiungendo cifre in primo piano . Quindi il controllo implica la ricerca di luoghi in cui le prime c cifre compaiano più avanti nella stringa (ovunque dopo le prime ccifre), e se ci sono tali posti, se la lunghezza intermedia è al massimo c.

(Naturalmente inverte la stringa prima della stampa.)

Potrebbe anche essere facilmente più veloce; Inizialmente avevo l'uscita anticipata da vari loop per efficienza, ma questo costava byte preziosi. n=1000Tuttavia, va ancora bene nell'intervallo di .

Ad ogni modo, il programma sembra mostrare una preferenza per le cifre più piccole, ma non è una preferenza molto forte. Ad esempio, eseguirlo con n=2000mi ha dato una stringa con 523zeri, 502uno, 497due e 478tre, che termina con 30210312013021. Quindi, se qualcun altro sta lavorando su un algoritmo avido, forse possono confermare questo risultato. O con n=1000ho ottenuto [263, 251, 248, 238]i conteggi per cifra.

Infine, vorrei menzionare che questi conteggi suggeriscono una sorta di simmetria, quasi (anche se non esattamente) come se avessimo iniziato con una distribuzione uniforme e poi convertito alcuni degli 3"in 0" e alcuni degli 2"in 1" S. Ma ovviamente potrebbe essere solo una coincidenza. Non ne ho idea!


1

Haskell, 115 (120 byte - 5 bonus)

x?_|or[t x==t(drop i x)|i<-[1..length x],t<-[take$div(i+1)2]]=[]
x?0=[x]
x?n=(?(n-1)).(:x)=<<"0123"
f=reverse.head.([]?)

Corri online su Ideone

Esempio di esecuzione:

*Main> f 40
"0120310213012310320130210312013210230120"
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.