Dove sono le piste in questa stringa infinita? (Trovato CCCCCC!)


25

A partire dalla stringa ABC, considera il risultato di aggiungere ripetutamente l'ultima metà di se stesso a se stesso (utilizzando la metà più grande se la lunghezza è dispari).

Otteniamo la progressione:

ABC
ABCBC
ABCBCCBC
ABCBCCBCCCBC
ABCBCCBCCCBCBCCCBC
etc...

Lasciate Srappresentare la stringa (o sequenza) infinita risultante che risulta quando questa procedura viene ripetuta per sempre.

Obbiettivo

L'obiettivo di questa sfida del codice è trovare l'indice della prima occorrenza di esecuzioni di C'in S.

All'inizio è facile: Cprima si presenta all'indice 2, CCalle 4, CCCalle 7, CCCCalle 26, ma CCCCCè completamente all'indice 27308! Dopodiché la mia memoria si esaurisce.

Il vincitore sarà l'invio che genera correttamente gli indici più eseguiti (in ordine, a partire da C). Puoi usare qualsiasi tipo di algoritmo ma assicurati di spiegarlo se non stai usando la forza bruta di base. L'input e l'output possono essere in qualsiasi formato di facile comprensione.

Nota importante: non so ufficialmente se Scontiene effettivamente tutte le esecuzioni di C. Questa domanda è derivata da questa nello scambio di stack di matematica , in cui neanche l'autore ha trovato CCCCCC. Sono curioso di sapere se qualcuno qui può. (Tale domanda è a sua volta basata sulla mia domanda originale sull'argomento .)

Se riesci a provare che non si Cverificano tutte le prove, Sallora vincerai automaticamente poiché questa domanda non sarà più valida. Se nessuno può dimostrarlo né trovarlo, CCCCCCil vincitore sarà la persona che può ottenere il limite inferiore più alto sull'indice di CCCCCC(o qualunque sia la più grande scala irrisolta se CCCCCCviene trovata).

Aggiornamento: Humongous kudos to isaacg and res che hanno trovato CCCCCCnell'indice astronomico di 2.124 * 10 ^ 519. Di questo passo non riesco a immaginare di trovarlo CCCCCCCcon alcun metodo che si basi sulla forza bruta. Buon lavoro ragazzi!


Non capisco - Stai dicendo che hai trovato CCCCCall'indice 27308, ma in seguito sembra che tu non sappia dove si verifica per primo. Volevi dire CCCCCC?
isaacg,

@isaacg Oops. 6 C è quello che è difficile da trovare. Lo aggiusterò.
Hobby di Calvin il

Se la congettura è errata, esiste una N per la quale c ^ N è la corsa più lunga. Sono abbastanza sicuro che dovrebbe essere possibile costruire una sequenza più lunga, portando a una contraddizione e dimostrando la congettura. Anche io non penso che sia troppo difficile, ma d'altra parte i problemi possono facilmente sottovalutare ...
Ingo Bürk,

Ritornerò sicuramente qui a mezzanotte con il mio nuovo gruppo di voti, sia per la domanda che per le risposte!
trichoplax,

Per coloro che stanno cercando, questo può rendere un po 'più semplice: se rimuovi la prima "A", devi solo giocare con "AB" e aggiungi metà + 1 per la successiva iterazione.
Faquarl

Risposte:


23

CCCCCC trovato a 2.124 * 10 ^ 519.

Indice precisa è 2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215

Trovato da res, usando il (vecchio versione di) codice qui sotto, dopo 3,5 ore di ricerca.

Attorno a quell'indice, la stringa è: ...BCCBCBCCCBCCCCCCBCCB...

Per verificare, modificare la riga indicata nel codice seguente per iniziare da 2946, anziché 5. La verifica richiede 20 secondi.

Aggiornamento: programma migliorato. Il vecchio programma ha cercato ~ 10 volte più posizioni del necessario.

La nuova versione trova CCCCCCin soli 33 minuti.

Come funziona il codice: Fondamentalmente, guardo solo le regioni che corrispondono alle estremità delle stringhe incrementali e calcolo le lettere guardando ricorsivamente alla stringa originale. Si noti che utilizza una tabella memo, che può riempire la memoria. Se necessario, mettere un cappuccio sulla lunghezza della tabella dei promemoria.

import time
import sys
sys.setrecursionlimit(4000)
ULIMIT=4000
end_positions=[]
current_end=2
while len(end_positions)<ULIMIT+3:
    end_positions.append(current_end)
    next_end=((current_end+1)*3+1)//2-1
    current_end=next_end
memo={}
def find_letter(pos):
    if pos in memo:
        return memo[pos]
    if pos<3:
        return 'ABC'[pos]
    for end_num in range(len(end_positions)-1):
        if pos>end_positions[end_num] and pos<=end_positions[end_num+1]:
            delta=end_positions[end_num+1]-end_positions[end_num]
            if len(memo)>5*10**6:
                return find_letter(pos-delta)
            memo[pos]=find_letter(pos-delta)
            return memo[pos]
time.clock()
for end_num in range(5,ULIMIT+1): # This line.
    diff = 1 # Because end_num is guaranteed to be a C
    while True:
        last_letter=find_letter(end_positions[end_num]+diff)
        if not last_letter=='C':
            break
        diff+=1
    if end_num%100==0:
        pos_str=str(end_positions[end_num])
        print(end_num,'%s.%s*10^%i'%(pos_str[0],pos_str[1:5],len(pos_str)-1),
        len(memo),diff,time.clock())
    if diff>=6:
        print(end_num,end_positions[end_num],diff,time.clock())

Max corrente cercato a: 4000 iterazioni

CCCCCC trovato in iterazione / i: 2946


Questo è Python giusto?
Hobby di Calvin il

Sì, lo aggiungerò.
Isaacg,

(+1) Il tuo programma, con sys.setrecursionlimit(4000)e ULIMIT=4000, ha rilevato (in circa 3,5 ore sul mio sistema) la prima occorrenza di CCCCCC all'indice = 2.124 * 10 ^ 519. L'indice esatto è nel prossimo commento ...
res

3
2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215
res

Eccezionale! Non ho mai sospettato che fosse così vicino al successo.
isaacg,

12

CCCCCC trovato a 2.124 * 10 ^ 519.

Il seguente codice rubino è stato utilizzato per la ricerca CCCCCC.

SEARCH = 6

k = [5,3]

getc=->i{
  j=i
  k.unshift(k[0]+(k[0]+1)/2)while(k[0]<=j)
  k.each_cons(2){|f,g|j-=f-g if j>=g}
  "ABC"[j]
}

while true
  x=k[0]
  x-=1 while getc[x]=="C"
  x+=1 
  l=1
  l+=1 while getc[x+l]=="C"

  break if l>=SEARCH
end

puts x
puts (x-14..x+l+13).map{|i|getc[i]}*""

L'indice è lo stesso della risposta di @isaacg .

Il tempo di esecuzione del codice sopra per 6 è nell'ordine di dieci secondi sul mio computer. Tuttavia, è ancora alla ricerca di una risposta per CCCCCCC(se si desidera provare da soli impostare costante SEARCHsu 7).

È possibile utilizzare getcper trovare il carattere in una posizione specifica icome viene fatto nell'ultima riga in cui è stampata la stringa attorno all'indice.


Ottimo lavoro per accelerarlo: la mia soluzione è stata molto approssimativa e non lucidata.
isaacg,

Qualcosa di strano: ho eseguito il codice sopra riportato fino all'iterazione # 34000 dopo aver rimosso l'interruzione e modificato un po 'i test, e trova solo una corsa di 6. È questo un problema con il codice (ne dubito) o è solo una strana proprietà della sequenza?
Isaacg,

@isaacg Notiamo che controlliamo solo le interruzioni di ogni sequenza e quindi perdiamo tutte le sequenze di copia C ^ 6. Alle pause sembrano essere molto rari, quindi penso che non vedremo presto un C ^ 7.
Howard,

Lo so, ma dal momento che uno è stato trovato in un'interruzione di sequenza dopo solo 2946 iterazioni, mi aspetto di vederne un secondo da 40000 iterazioni, che è dove sono ora.
isaacg,

@isaacg Puoi usare il codice (molto più veloce) qui: ideone.com/HoEKOB . Anche con quello non sono riuscito a trovare un altro C ^ 6 in un punto di sequenza (ancor meno un C ^ 7).
Howard,

5

(Non una risposta, ma troppo lungo per un commento.)

Quella che segue è una traduzione Python del programma Ruby di @ Howard (accelerato di un fattore vicino a 3 avendo solo uno getcnel ciclo di ricerca). Sul mio sistema, questo trova il primo C ^ 6 in 3 secondi. In 93 ore, non trova C ^ 7 in 231.000 iterazioni, quindi il primo C ^ 7 (se esiste) deve verificarsi dopo le posizioni 10 ^ 40677 più a sinistra nella stringa infinita.

import time

L = [5, 3]      #list grows "backwards" (by insertion on the left)

def getc(i):    #return the letter at index i
    while L[0] <= i: L.insert(0,L[0] + (L[0] + 1)//2)
    for k in range(len(L)-1): 
        if i >= L[k+1]: i -= L[k] - L[k+1]
    return 'abc'[i]

def search(k):  #find the first occurrence of c^k
    start = time.time()
    iter = 0
    while True:
        iter += 1
        if iter % 1000 == 0: print iter, time.time()-start
        p = L[0] - 1
        l = 1
        while getc(p+l)=='c': l += 1
        if l == k: break 
    return p, iter, time.time()-start

k = 6

(indx, iter, extime) = search(k)
print 'run length:', k
print 'index:', indx, '    (',len(str(indx)),'digits )'
print 'iteration count:', iter
print 'neighborhood:', ''.join([getc(i) for i in range(indx-1,indx+k+10)])
print 'execution time:', extime

Con PyPy, trova C ^ 6 in meno di un secondo sulla mia macchina.
Dennis,
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.