素数生成拼图(边缘案例)

时间:2017-01-04 08:36:20

标签: python primes puzzle

我在编码网站上解决了以下问题。它在测试(隐藏测试)上遇到了一些边缘情况,但我不确定它们是什么。有人看到任何问题吗?

问题:让A成为所有素数的字符串,按顺序压在一起(即235711131719...)。给定索引n,返回一个5位数的字符串,其中第一个数字位于A中的索引n

e.g。 foo(0) => 23571foo(10) => 19232

这是我的代码:

def gen_primes():                                                                                                                                                                                                    
    A = {}                                                                                                                                                                                                           
    i = 2                                                                                                                                                                                                            
    while True:                                                                                                                                                                                                      
        if i not in A:                                                                                                                                                                                               
            yield i                                                                                                                                                                                                  
            A[i * i] = [i]                                                                                                                                                                                           
        else:                                                                                                                                                                                                        
            for p in A[i]:                                                                                                                                                                                           
                A.setdefault(p + i, []).append(p)                                                                                                                                                                    
            del A[i]                                                                                                                                                                                                 
        i += 1                                                                                                                                                                                                       

def answer(n):                                                                                                                                                                                                       

    counter = 0                                                                                                                                                                                                      
    prime_string = ""                                                                                                                                                                                                

    for p in gen_primes():                                                                                                                                                                                           
        if (counter >= n):
            prime_string += str(p)                                                                                                                                                                                   
        counter += len(str(p))                                                                                                                                                                                       
        if len(prime_string) >= 5:                                                                                                                                                                                   
            break                                                                                                                                                                                                    

    return prime_string[:5]    

3 个答案:

答案 0 :(得分:2)

我认为这可能会突破多个数字的素数:

我们假设我们已经到达了三位数的素数,如103。 Counter为10,n为11(这只是一个例子,我不知道这个确切的星座是否会出现)

然后我们需要使用数字" 03"超出" 103"。但由于counter小于n,因此会跳过整个素数。该计划将继续107。

您可以通过完全删除counter来解决此问题:始终将字符串添加到字符串中,如果字符串的长度为n+5或更长,则跳出循环。

编辑:

我已检查过您的代码:例如answer(5)answer(6)。使用您的代码,两个调用都会产生" 13171"。 " 11"的第二个数字被跳过了。

使用此代码:

def answer(n):                                                                                                                                                                                                       

    counter = 0                                                                                                                                                                                                      
    prime_string = ""                                                                                                                                                                                                

    for p in gen_primes():
        prime_string += str(p)                                                                                                                                                                                     
        if len(prime_string) >= n+5:                                                                                                                                                                                   
            break                                                                                                                                                                                                    

    return prime_string[n:n+5] 

他们导致

11317  # answer(5)
13171  # answer(6)

答案 1 :(得分:0)

这是我的答案;它类似于@lhk,但使用滑动窗口而不是存储整个字符串:

phil@haydn ~ $ python
Python 2.7.5+ (default, Sep 17 2013, 15:31:50) 
[GCC 4.8.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def primegen(): # http://stackoverflow.com/a/20660551
...     yield 2; yield 3          # prime (!) the pump
...     ps = primegen()           # sieving primes
...     p = next(ps) and next(ps) # first sieving prime
...     D, q, c = {}, p*p, p      # initialize
...     def add(x, s):            # insert multiple/stride
...         while x in D: x += s  #   find unused multiple
...         D[x] = s              #   save multiple/stride
...     while True:               # infinite list
...         c += 2                # next odd candidate
...         if c in D:            # c is composite
...             s = D.pop(c)      #   fetch stride
...             add(c+s, s)       #   add next multiple
...         elif c < q: yield c   # c is prime; yield it
...         else: # (c == q)      # add sqrt(c) to sieve
...             add(c+p+p, p+p)   #   insert in sieve
...             p = next(ps)      #   next sieving prime
...             q = p * p         #   ... and its square
... 
>>> def primeSubstr(n): # nth character in concatenated primes
...     ps = primegen()           # sequence of prime numbers
...     i, s = 0, ''              # current index, sliding window
...     while True:               # do ... until i == n
...         if len(s) < 5:        # sliding window too small
...             s+=str(next(ps))  #   add next prime to window
...         elif i < n:           # not yet to target index
...             i, s = i+1, s[1:] #   slide window to right
...         else: return s[:5]    # return desired substring
... 
>>> primeSubstr(0)
'23571'
>>> primeSubstr(5)
'11317'
>>> primeSubstr(10)
'19232'
>>> primeSubstr(15)
'93137'
>>> primeSubstr(20)
'41434'
>>> primeSubstr(1000)
'98719'
>>> CTRL-D

我明天将在my blog讨论这个问题。

答案 2 :(得分:0)

这看起来像itertools的工作,这个怎么样

>>> from sympy import sieve
>>> from itertools import islice, chain
>>> def primeSubStr(n):
        primes=iter(sieve)
        next(primes)
        return "".join( islice( chain.from_iterable(map(str,primes)), n, n+5))

>>> primeSubStr(0)
'23571'
>>> primeSubStr(10)
'19232'
>>> primeSubStr(5)
'11317'
>>> primeSubStr(15)
'93137'
>>> primeSubStr(20)
'41434'
>>> primeSubStr(1000)
'98719'
>>> primeSubStr(2000)
'98940'
>>> 

为简单起见,我使用sympy.sieve来获取素数,但任何获得素数的方法都可以正常工作,例如here

现在是有趣的部分,地图非常明显,我们得到一个"2", "3", "5", "7", "11", "13", ... "101", "103", ...流,然后是chain.from_iterable,这个流在单个数字"2", "3", "5", "7", "1","1", "1","3", ... "1","0","1", "1","0","3", ...的流中被分解,最后与islice我们采取我们想要的部分并加入它以获得最终结果