这个无限字符串中的游程在哪里?(找到CCCCCC!)


25

从字符串开始ABC,考虑将其后半部分重复附加到自身的结果(如果长度为奇数,则使用较大的一半)。

我们得到进展:

ABC
ABCBC
ABCBCCBC
ABCBCCBCCCBC
ABCBCCBCCCBCBCCCBC
etc...

让我们S代表由于此过程被永久重复而产生的结果无限字符串(或序列)。

目标

在此代码的挑战目标是找到的运行中第一次出现的指数C的中S

一开始很容易:C首先在index 2CCat 4CCCat 7CCCCat出现26,但CCCCC一直在index处27308!之后,我的记忆就用光了。

获胜者将是能够正确生成最多运行索引的提交(按顺序从开始C)。您可以使用任何种类的算法,但是如果您不使用基本的暴力手段,请务必对其进行解释。输入和输出可以采用任何易于理解的格式。

重要说明:我不正式知道是否S实际包含的所有运行C。这个问题是从“数学堆栈交换”上的一个问题中得出的,在该问题中作者也没有找到CCCCCC。我很好奇这里是否有人可以。(该问题又是基于我对该主题的原始问题。)

如果您可以证明并非所有的都可以C参加,S那么您将自动赢得比赛,因为该问题将不再有效。如果没有人能证明也找不到,CCCCCC那么获胜者将是可以得到指数最高下限的人CCCCCC(或者CCCCCC找到最大的未解决奔波的人)。

更新:了Humongous荣誉给isaacgRES谁发现CCCCCC的2.124×10 ^ 519天文指数。以这样的速度,我无法想象找到CCCCCCC任何依靠蛮力的方法。干得好!


我不明白-您是说您CCCCC在索引27308中找到了,但是后来听起来您好像不知道它第一次出现的位置。你是说CCCCCC
isaacg 2014年

@isaacg糟糕。6 C是很难找到的。我会解决的。
卡尔文的爱好2014年

如果猜想是错误的,则存在一个N,其c ^ N是最长的运行时间。我非常确定应该可以构造更长的序列,从而导致矛盾并证明猜想。我也不认为这太难了,但另一方面,问题很容易被低估了
IngoBürk2014年

我肯定会在午夜回到我这里,获得我的新一批选票-无论是问题还是答案!
trichoplax 2014年

对于那些正在搜索的用户,这可以使操作变得容易一些:如果删除了第一个“ A”,则只需要使用“ AB”,然后为下一个迭代附加half + 1。
Faquarl

Answers:


23

CCCCCC位于2.124 * 10 ^ 519。

精确的指标是2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215

经过3.5小时的搜索,使用下面的(旧版本)代码通过res找到了。

在该索引周围,字符串为: ...BCCBCBCCCBCCCCCCBCCB...

要进行验证,请将下面代码中的指示行更改为从2946开始,而不是5。验证需要20秒。

更新:改进程序。旧程序搜索的位置超出了所需数量的10倍。

新版本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


这是Python吗?
加尔文的爱好2014年

是的,我将其添加。
isaacg 2014年

(+1)使用sys.setrecursionlimit(4000)ULIMIT=4000,您的程序(在我的系统上大约3.5个小时内)发现CCCCCC首次出现在索引= 2.124 * 10 ^ 519。确切的索引在下一条评论中……
res 2014年

3
2124002227156710537549582070283786072301315855169987260450819829164756027922998360364044010386660076550764749849261595395734745608255162468143483136030403857241667604197146133343367628903022619551535534430377929831860918493875279894519909944379122620704864579366098015086419629439009415947634870592393974557860358412680068086381231577773140182376767811142988329838752964017382641454691037714240414750501535213021638601291385412206075763857490254382670426605045419312312880204888045665938646319068208885093114686859061215
水库

太棒了!我从不怀疑它是如此接近成功。
isaacg 2014年

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的答案相同。

在我的计算机上,以上代码的运行时间为10秒。不过,它仍在寻找答案CCCCCCC(如果您想尝试将其设置SEARCH为,则可以自己尝试7)。

您可以使用getc该字符在特定位置查找字符,i就像在打印索引周围的字符串的最后一行中所做的那样。


做得好,加快速度-我的解决方案非常粗糙且粗糙。
isaacg 2014年

有点奇怪:在删除中断并稍微更改了测试之后,我已经将上述代码运行到了#34000迭代,它只能找到一次运行6。这是否是代码问题(我对此表示怀疑)还是这只是序列的一个奇特性质吗?
isaacg 2014年

@isaacg请注意,我们仅检查每个序列的间断,因此错过了所有复制序列C ^ 6。在休息时,这些似乎很少见-因此,我认为我们不会很快看到C ^ 7。
2014年

我知道,但是由于仅在2946次迭代后就发现了一个序列中断,所以我希望看到40000次迭代后再发现一个,这就是我现在的位置。
isaacg 2014年

@isaacg您可以在此处使用(快得多)代码:ideone.com/HoEKOB。即使这样,我也无法在序列点找到另一个C ^ 6(甚至更不用说C ^ 7)。
霍华德

5

(不是答案,但是评论太久了。)

以下是@Howard的Ruby程序的Python翻译(通过getc在搜索循环中仅添加一个,将速度提高了近3倍)。在我的系统上,这会在3秒内找到第一个C ^ 6。在93小时内,它在231,000次迭代中没有发现C ^ 7,因此第一个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。
丹尼斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.