我在编码网站上解决了以下问题。它在测试(隐藏测试)上遇到了一些边缘情况,但我不确定它们是什么。有人看到任何问题吗?
问题:让A
成为所有素数的字符串,按顺序压在一起(即235711131719...
)。给定索引n
,返回一个5位数的字符串,其中第一个数字位于A中的索引n
。
e.g。 foo(0) => 23571
和foo(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]
答案 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
我们采取我们想要的部分并加入它以获得最终结果