【问题标题】:Circular Primes Project Euler #35圆形素数项目 Euler #35
【发布时间】:2019-04-13 10:37:23
【问题描述】:

这是我要解决的问题。

数字 197 被称为圆素数,因为 数字:197、971 和 719 本身就是质数。

100 以下的素数有 13 个:2、3、5、7、11、13、17、31、 37、71、73、79 和 97。

一百万以下有多少个圆素数?

这是我的尝试。我首先将所有低于 1000000 的素数放在一个称为素数的列表中,然后计算它们所有可能的排列并将这些排列存储在一个列表中。然后我检查了这些排列是否是素数。

import math
def isPrime(num):
    flag = 1
    root = int(math.sqrt(num) + 1)
    for i in range (2,root+1):
        if num%i == 0:
            flag = 0
            break
        else:
            flag = 1
    if flag == 1:
        return True
    else:
        return False

primes = [#list of all primes below 1000000]

def permutations(word):
    if len(word) == 1:
        return [word]
    char = word[0]
    perms = permutations(word[1:])
    result = []
    for perm in perms:
        for i in range (len(perm)+1):
            result.append(perm[i:] + char + perm[:i])
    return result

count = 0
for i in primes:
    to_be_tested = permutations(str(i))
    count_to_be_fulfilled = len(to_be_tested)
    new_count = 0
    for j in to_be_tested:
        if isPrime(int(j)):
            new_count += 1
    if new_count == count_to_be_fulfilled:
        count += 1
print(count)

我得到的答案是 22,但根据 Project Euler,这是错误的。我不知道答案,因为我想自己解决这个问题,不想作弊。请告诉我我做错了什么。

【问题讨论】:

  • 另外这段代码需要大约 5 分钟才能执行,所以如果有更有效的方法,请告诉我。
  • 我没有时间浏览代码,但如果你使用集合而不是列表,它会更快
  • 而且由于列表中已经有素数(或者如果您更改了集合),您可以检查该数据结构中是否有一个数字来测试它是否是素数
  • 同意@Kacper 使用集合。在这里查看加快列出素数的速度:stackoverflow.com/questions/2068372/…。对于您的排列函数,我认为您可以通过使用字符串将一位数字从前到后循环 n 次(其中 n 是素数的长度)来简化它。使用简化函数创建一组潜在的圆形素数,并使用交集来检查该集合是否确实是一组素数。
  • 这个问题只涉及rotations,那么你为什么要生成(和测试)候选编号的所有排列?您是否针对问题中显示的素数 197 运行了代码?

标签: python python-3.x permutation primes


【解决方案1】:

解决方案

我将发布完整的解决方案,因为来自Project Euler's about 部分:

我学到了很多解决问题 XXX 所以可以发布我的 其他地方的解决方案?

看来您已经回答了自己的问题 问题。没有什么比得上“啊哈!”当你 终于解决了一个你已经研究了一段时间的问题。 通常是出于好意,希望与我们分享我们的 洞察力,以便其他人也可以享受那一刻。然而可悲的是, 对于您的读者来说,情况并非如此。真正的学习是一种主动 过程并看到它是如何完成的距离体验还有很长的路要走 发现的顿悟。请不要否认别人你所拥有的 非常重视自己。

不过,我会给你一些提示。

数据结构

正如我在评论中提到的,使用集合将大大提高程序的性能,因为访问其中的数据非常快(您可以通过谷歌搜索一种称为 hashing 的技术来检查原因如果你不知道的话)。准确地说,使用列表的性能将是O(N),而使用集合的性能大约是O(1)

旋转与排列

在问题陈述中,您需要计算一个数字的旋转。正如@ottomeister 所指出的,您应该真正检查您的程序是否正在执行问题陈述所期望的操作。目前,调用permutations("197") 将返回以下列表 - ['791', '917', '179', '971', '719', '197'] - 而问题预计结果为['197', '971', '719']。而不是创建 排列,您应该计算 rotations,例如,可以通过将每个数字向左移动(环绕)直到返回初始数字(可以如果你真的喜欢那些递归算法,那就做一个这样的算法)。

质数检查

您当前正在通过执行一个循环来检查每个数字是否为素数,该循环检查数字N 是否可以被直到sqrt(N) 的所有内容整除。正如您所注意到的,这对于很多数字来说非常慢,并且有更好的方法来检查一个数字是否是素数。在您的场景中,理想的解决方案是简单地执行N in primes,因为您已经生成了质数,如果您使用集合而不是列表,它将是O(1)。或者,您可以查看primality tests(尤其是启发式和概率测试)

终于

我通常建议测试您自己的解决方案,然后再进行其他所有操作,您可能很容易发现您的permutations 函数根本不符合问题陈述的预期结果。我建议将事情进一步分解成更小的函数,例如你可以有一个类似于你的permutationsrotations(number) 函数,也许是一个is_circular(number) 函数来检查给定的数字是否满足问题要求和count_circular(upper_bound) 函数来计算和计算循环数。如果您还随时评论所有内容,它将使调试变得更加容易,并且您将能够在旅途中确认一切都按预期工作:)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 1970-01-01
    • 2012-11-10
    相关资源
    最近更新 更多