计算长度不超过6的不同素数子字符串的总数

时间:2019-03-01 08:16:29

标签: python optimization

#code for SieveOfEratosthenes here

SieveOfEratosthenes=SieveOfEratosthenes(999999)

t = int(input().strip())
for a0 in range(t):
  N= input()
  prime=set()
  for w in range(1,7):
    for i in range(0,len(N)):
      substring=int(N[i:i+w])
      if(N[i:i+w][-1]!=4 and N[i:i+w][-1]!=6 and N[i:i+w][-1]!=8 and N[i:i+w][-1]!=0):
        if(len(str(substring))==w and substring in SieveOfEratosthenes):
          prime.add(substring)
  print(len(prime))

此代码正常工作,但超时会导致超时。
问:如何对其进行优化?

1 个答案:

答案 0 :(得分:0)

您没有提供测试用例的示例,因此我们不知道它何时失败。 但是在这里,我给出了代码的优化版本;至少我认为我了解您要做什么。

首先,我介绍了一个筛子的实现(不是我自己的发明,它的源代码在函数docstring中):

def generate_primes():
    """
    Generate an infinite sequence of prime numbers.

    Sieve of Eratosthenes
    Code by David Eppstein, UC Irvine, 28 Feb 2002
    http://code.activestate.com/recipes/117119/
    https://stackoverflow.com/a/568618/9225671
    """
    # Maps composites to primes witnessing their compositeness.
    # This is memory efficient, as the sieve is not "run forward"
    # indefinitely, but only as long as required by the current
    # number being tested.
    D = {}

    # The running integer that's checked for primeness
    q = 2

    while True:
        if q not in D:
            # q is a new prime.
            # Yield it and mark its first multiple that isn't
            # already marked in previous iterations
            yield q
            D[q * q] = [q]
        else:
            # q is composite. D[q] is the list of primes that
            # divide it. Since we've reached q, we no longer
            # need it in the map, but we'll mark the next
            # multiples of its witnesses to prepare for larger
            # numbers
            for p in D[q]:
                D.setdefault(p + q, []).append(p)
            del D[q]

        q += 1

如果不使用全局变量,Python代码通常会运行得更快,因此我将所有代码放入一个函数中。我还:

  • 在开始时生成素数的set(而不是list,因为set提供了更快的成员资格检查。)
  • 删除了行

    if(N[i:i+w][-1]!=4 and N[i:i+w][-1]!=6 and N[i:i+w][-1]!=8 and N[i:i+w][-1]!=0):
    

    ,因为它没有任何作用; N[i:i+w][-1]是子字符串的最后一个字符,类型为str,因此永远不会等于int

我的版本如下:

def func():
    max_prime_number = 10**6
    primes_set = set()
    for n in generate_primes():
        if n < max_prime_number:
            primes_set.add(n)
        else:
            break
    print('len(primes_set):', len(primes_set))

    while True:
        print()
        input_str = input('Enter "input_str":').strip()
        if len(input_str) == 0:
            break

        print('Searching prime substring in', input_str)
        prime_substrings = set()
        for w in range(1, 7):
            for i in range(len(input_str)):
                n = int(input_str[i:i+w])
                sub_str = str(n)        # may be shorter than 'w' if it had leading zeros

                if len(sub_str) == w:
                    if n in primes_set:
                        prime_substrings.add(sub_str)
        print('len(prime_substrings):', len(prime_substrings))