项目Euler#5使用python

时间:2015-08-05 19:02:20

标签: python python-2.7

问题陈述是这样的:

  

2520是可以除以1到10之间的每个数字的最小数字,没有任何余数。

     

从1到20的所有数字均可被整除的最小正数是多少?

这是我的解决方案:

x=2520.0
list=[]
true_list=[11.0, 12.0, 13.0, 14.0, 16.0, 17.0, 18.0, 19.0, 20.0]
b=1
def test():
    for n in true_list:
        z=x/n
        if z%2==0:
            list.append(n)
while b==1:
    test()
    if list==true_list:
        b=2
        print x
    else:
        x=x+20
        list=[]

- >基本上,我已经定义了一个空列表,它由函数test()填充。 test()的作用是检查给定的数字(在这种情况下为x)是否可以被11-20的值整除。如果是,则将该值(在11-20之间)放在空列表中。

当test()运行时,程序检查列表是否等于预定义的true_list,其中包含11-20的所有数字。如果是,则打印x。否则,程序在递增x的值后继续。

这意味着如果list等于true_list,则11-20中的所有数字均匀划分我们的数字(x),这就是问题中的问题。

它给出答案:465585120.0,运行一分钟左右。这恰好是不正确的。我不知道为什么会这样。我一直试图解决这个问题8个多小时,而且我的智慧结束了。错误是什么?

您不需要提前阅读,但如果您对我在解决方案中使用某些内容的原因有疑问,那么我在这里解决了其中的一些问题:

- >我没有使用true_list中的所有20个数字来加速程序,因为任何可被11-20整除的数字也可以被1-20整除。

- >我使用x = x + 20来加速程序,因为它与x = x + 1或x + 2一样有效;只是,它更快。

- >我使用了浮点值,因为我在函数'test()'中使用z = x / n,我不想删除小数部分,因为这样做会使得偶数浮点值符合条件后续操作,即z%2。

示例:

1)使用int值:

x=17
n=2
z=x/n=8

这里,z%2 == 0是有效的,不应该是这种情况,因为它在数学中实际上没有效。

2)浮动值:

x=17.0
n=2.0
z=x/n=8.5

在这里,z%n != 0应该如何。

6 个答案:

答案 0 :(得分:2)

像其他人提到的那样只需找到lcm,但这里有一个简单的方法。记住lcm(a,b,c)= lcm(a,lcm(b,c))。这就是:

from fractions import gcd

print(reduce(lambda a, b: a * b / gcd(a, b), range(1, 21)))

如果你想编写自己的gcd函数,它的工作原理如下(https://en.wikipedia.org/wiki/Euclidean_algorithm):

def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a

答案 1 :(得分:0)

首先,正如我在评论中所说的那样,你为什么要以蛮力的方式去做?您可以在几秒钟内更轻松地计算数字1到20的最小公倍数。

其次,您的代码行

if z%2==0:
        list.append(n)

这基本上可以让你得到你想要的答案的两倍,因为这句话会让你计算LCM * 2,因为它必须分成额外的2倍。

正确的答案是232792560,我用一张纸和一台计算器计算得出< 20秒。 如你所见,你得到的答案是双倍

< - 编辑我以前的代码错了。这个工作----->

您可以通过执行以下操作来解决此问题:

x=2520.0
list=[]
true_list=[11.0, 12.0, 13.0, 14.0, 16.0, 17.0, 18.0, 19.0, 20.0]
b=1
def test():
     for n in true_list:
        if x%n==0:
            list.append(n)
while b==1:
    test()
    if list==true_list:
        b=2
        print(x)
    else:
        x=x+20
        list=[]

通过制定LCM,您可以做到这一点:

allFactors={}
#for each divisor (ignore 1 as it can divide into everything)
for n in range(2,21,1):
    factors={}
    i=2
    while i<=n:
        while n%i==0:
            try:
                factors[i]+=1
            except KeyError:
                factors[i]=1
            n=n/i
        i+=1

    for pf,v in factors.iteritems():
        try:
            if allFactors[pf] < v:
                allFactors[pf]=v
        except KeyError:
            allFactors[pf]=v
lcm=1
for pf,v in allFactors.iteritems():
    lcm=lcm*(int(pf)**v)

print(lcm)

答案 2 :(得分:0)

Tht %运算符称为“模数”运算符。在英语中:a % b读作“a mod b”,意思是“a/b的剩余部分”。所以100%3=112%5=2

检查可分性的常用方法是检查“我的数字是否等于我的除数等于0?”。或者在代码中:

if a%b == 0:
    print("b divides a!")

在您的代码中,您要检查n是否划分x。你查了一下:

z=x/n
if z%2==0:
    print("n divides x?") #No not really

zxn的商。 if z%2==0可以解释为“如果z可以被2整除”。 所以你问“x和n的商是否被2整除?”当然,这与你想要的无关。而只是做

if x%n==0:
    print("n divides x?") # YES!

我建议你做几个python教程,这样你就可以在尝试问题之前先掌握基础知识。 :)

如果您需要帮助,请告诉我们。 :)

答案 3 :(得分:0)

有很多方法可以解决这个问题。由于您正在使用Project Euler进行早期练习,我想您希望开发一种方法来帮助您理解基本的Python结构(与使用gcd的“包含电池”方法相反)等等

这是一个基本的方法,在运行时或开发时间效率不高:)但是一个体面的练习:

found = None
n = 0

while not found:
    n += 1
    for d in xrange(2,21):
        if n % d:
            break
    else:
        found = n

print found

这是这样的:

  • 从0开始检查分子n。(实际上你可以从2520开始,因为我们知道答案必须不小于1-10案例的答案,但这是一个很小的优化。 )

  • 永远循环,直到找到解决方案。 (在现实世界的程序中,你可能会进行某种安全检查,所以这不能永远运行,但这对我们正在做的事情来说很好。)

  • 如果我们还没有找到解决方案,请在下一轮将分子加一。

  • 将分子除以2-20范围内的分母d。如果d的任何值导致非零余数,则跳出循环 - 测试剩余分母没有意义。 (如果我们想要更有效率,我们可以使用xrange(2,n),因为没有必要除以大于分子的值。如果效率是一个极端的问题,就像范围大得多(2-1000)而不是2-20),我们实际上可以使用xrange(2,floor(sqrt(n)),因为除数的平方根不可能没有余数。

  • 如果我们在for循环中一直进行,而不会提前中断,else子句会运行,我们会记录分子的临界值 - 这就是解决方案。

这种做法显然是蛮力。学习练习很好。对于相同问题的较大版本,使用Euclid算法和硬件感知优化会更好。

答案 4 :(得分:0)

import time
start_time = time.time()

for i in range(2520,10000000000):
    if i % 11 == 0 and\
    i % 12 == 0 and\
    i % 13 == 0 and\
    i % 14 == 0 and\
    i % 15 == 0 and\
    i % 16 == 0 and\
    i % 17 == 0 and\
    i % 18 == 0 and\
    i % 19 == 0 and\
    i % 20 == 0:
        print(i)
        break

print(time.time() - start_time," seconds")

答案 5 :(得分:0)

您可以分别找到质数和合数的 LCM,然后找到它们的 LCM 的 LCM。在几乎一秒钟内完成工作!这是我的代码:

import time

start_time = time.time()
nums = []
primeNums = []
allNums = []

def findFactors(num):
    factors = []
    for i in range(1, num + 1):
        if num % i == 0:
            if i not in factors:
                factors.append(i)
                x = int(num / i)
                factors.append(x)
            else:
                break
    return factors
 

def isDivisibleByAll(number, numbers):
    isDivisbleBy = []
    for num in numbers:
        if number % num == 0:
            isDivisbleBy.append(num)
    return isDivisbleBy == numbers



for i in range(11, 21):
    nums.append(i)

for num in nums:
    if findFactors(num) == [1, num]:
        primeNums.append(num)
        nums.remove(num)

currentNum = nums[-1]
currentPrimeNum = primeNums[-1]
while isDivisibleByAll(currentNum, nums) == False:
    currentNum = currentNum + nums[-1]
    print(currentNum)

while isDivisibleByAll(currentPrimeNum, primeNums) == False:
    currentPrimeNum = currentPrimeNum + primeNums[-1]
    print(currentPrimeNum)

allNums.append(currentNum)
allNums.append(currentPrimeNum)
currentAllNum = allNums[-1]

while isDivisibleByAll(currentAllNum, nums) == False:
    currentAllNum = currentAllNum + allNums[-1]
    print(currentAllNum)

print(currentNum, currentPrimeNum, currentAllNum)
end_time = time.time()

print("Time taken: ", end_time - start_time)