Де прогони в цій нескінченній струні? (Знайдено CCCCCC!)


25

Починаючи з рядка ABC, розглянемо результат багаторазового додавання останньої половини до себе (використовуючи більшу половину, якщо довжина непарна).

Ми отримуємо прогресування:

ABC
ABCBC
ABCBCCBC
ABCBCCBCCCBC
ABCBCCBCCCBCBCCCBC
etc...

Нехай Sпредставляє результуючу нескінченну рядок (або послідовність), що призводить до того, що ця процедура повторюється назавжди.

Мета

Мета в цьому виклику коду - знайти індекс першого появи запусків Cs у S.

Спочатку це легко: Cспочатку виникає в індексі 2, CCу 4, CCCна 7, CCCCу 26, але CCCCCвесь шлях в індексі 27308! Після цього моя пам’ять закінчується.

Переможцем стане подання, яке правильно генерує найбільш запущені індекси (для порядку, починаючи з C). Ви можете використовувати будь-який алгоритм, але обов'язково поясніть це, якщо ви не використовуєте основну грубу силу. Введення та вихід можуть бути в будь-якому простому для розуміння форматі.

Важлива примітка: Я офіційно не знаю, Sмістить чи ні насправді всі запуски C. Це запитання випливає з цього питання на Mat Exchange Stack Exchange , в якому автор так і не знайшов CCCCCC. Мені цікаво, якщо хто тут може. (Це запитання, в свою чергу, ґрунтується на моєму первісному питанні з цієї теми .)

Якщо ви зможете довести, що не всі запуски Cтрапляються, Sви виграєте автоматично, оскільки це питання більше не буде дійсним. Якщо ніхто не може довести, що ні знайти, CCCCCCто переможцем буде та людина, яка зможе отримати найвищу нижню межу індексу CCCCCC(або будь-якого найбільшого невирішеного пробігу, якщо CCCCCCбуде знайдено).

Оновлення: Гумонні кудо до isaacg і res, які знайшли CCCCCCза астрономічним показником 2.124 * 10 ^ 519. З цією швидкістю я не можу уявити, щоб знайти CCCCCCCбудь-який метод, який спирається на грубу силу. Гарна робота хлопці!


Я не розумію - Ви кажете, що знайшли CCCCCв індексі 27308, але пізніше це здається, що ви не знаєте, де це вперше відбувається. Ви мали на увазі CCCCCC?
isaacg

@isaacg На жаль. 6 C - це той, який важко знайти. Я це виправлю.
Захоплення Кальвіна

Якщо гіпотеза неправильна, існує N, для якого c ^ N - найдовший пробіг. Я впевнений, що слід створити більш довгу послідовність, що призведе до суперечності та доведення гіпотези. Я також не думаю, що це занадто важко, але, з іншого боку, проблеми можна легко недооцінити ...
Ingo Bürk

Я обов'язково повертаюся сюди опівночі зі своєю новою партією голосів - і за питання, і за відповіді!
трихоплакс

Для тих, хто шукає, це може зробити трохи простіше: Якщо ви видалите перший "A", тоді вам потрібно буде лише пограти з "AB", і ви додасте половину + 1 для наступної ітерації.
Faquarl

Відповіді:


23

CCCCCC знайдено в 2.124 * 10 ^ 519.

Точний показник 2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215

Знайдено за res, використовуючи (стару версію) код нижче, після 3,5 годин пошуку.

Навколо цього індексу рядок: ...BCCBCBCCCBCCCCCCBCCB...

Щоб перевірити, змініть вказаний рядок у наведеному нижче коді, щоб почати з 2946, замість 5. Перевірка займає 20 секунд.

Оновлення: Покращена програма. Стара програма шукала ~ 10x більше локацій, ніж потрібно.

Нова версія знайдеться CCCCCCлише за 33 хвилини.

Як працює код: В основному я дивлюся лише на регіони, які відповідають кінці покрокових рядків, і обчислюю літери, рекурсивно оглядаючись назад до початкового рядка. Зауважте, що він використовує таблицю нагадування, яка може заповнити вашу пам'ять. Покладіть шапку на довжину столу пам’яті, якщо необхідно.

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

Поточний макс. Пошук: 4000 ітерацій

CCCCCC знайдено при ітерації: 2946


Це Пітон, правда?
Захоплення Кальвіна

Так, я додам це.
isaacg

(+1) Ваша програма, з sys.setrecursionlimit(4000)і ULIMIT=4000, знайшов (приблизно 3,5 години на моїй системі) перше входження CCCCCC на індекс = 2,124 * 10 ^ 519. Точний індекс - у наступному коментарі ...
res

3
2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215
рес

Дивовижно! Я ніколи не підозрював, що це так близько до успіху.
isaacg

12

CCCCCC знайдено в 2.124 * 10 ^ 519.

Для пошуку був використаний наступний код рубіну 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]}*""

Індекс такий самий, як у відповіді @isaacg .

Виконання вищевказаного коду на 6 на моєму комп’ютері складає десять секунд. Тим не менш, це все ще шукає відповідь CCCCCCC(якщо ви хочете спробувати його, встановіть постійне SEARCHзначення 7).

Ви можете використовувати getcсимвол у визначеному положенні, iяк це робиться в останньому рядку, де друкується рядок навколо індексу.


Хороша робота пришвидшила його - моє рішення було дуже грубим і неповажним.
isaacg

Щось дивне: я запустив вищезазначений код до ітерації №34000 після видалення перерви та трохи зміни тестів, і він виявляє лише один пробіг 6. Це проблема з кодом (я сумніваюся в цьому) або це просто незвичайна властивість послідовності?
isaacg

@isaacg Зауважимо, що ми перевіряємо лише перерви кожної послідовності і, таким чином, пропускаємо всі послідовності копіювання C ^ 6. На перервах це здається дуже рідкісним, тому я думаю, що ми скоро не побачимо С ^ 7.
Говард

Я знаю, але оскільки один був знайдений на перерві послідовності після лише 2946 ітерацій, я очікував би побачити другий за 40000 ітерацій, який я зараз перебуваю.
isaacg

@isaacg Ви можете використовувати (набагато швидше) код тут: ideone.com/HoEKOB . Навіть при цьому я не міг знайти іншого C ^ 6 в точці послідовності (ще менше C ^ 7).
Говард

5

(Не відповідь, але занадто довго для коментаря.)

Далі йде переклад Python програми @ Howard's Ruby (прискорений на коефіцієнт біля 3, маючи лише один getcу циклі пошуку). У моїй системі це знаходить перший C ^ 6 за 3 секунди. За 93 години він не знаходить C ^ 7 в 231 000 ітераціях, тому перший C ^ 7 (якщо він існує) повинен відбуватися після крайнього лівого 10 ^ 40677 положення в нескінченному рядку.

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

З PyPy він знаходить C ^ 6 менше ніж на секунду на моїй машині.
Денніс
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.