我在Project Euler中遇到问题5:“2520是可以除以1到10之间的每个数字的最小数字,没有任何余数。
从1到20的所有数字均可被整除的最小正数是多少?“
我构造了以下代码,当使用1 - 10作为除数时找到正确的值2520,但是当使用1 - 20时代码似乎永远存在。 我再次不希望代码只是一个指针或两个我错的地方。 感谢
def smallestDiv(n):
end=False
while end == False:
divisors = [x for x in range(1,21)] # get divisors
allDivisions = zip(n % i for i in divisors) # get values for n % all integers in divisors
check = all(item[0] == 0 for item in allDivisions ) # check if all values of n % i are equal to zero
if check: # if all values are equal to zero return n
end = True
return n
else: # else increase n by 1
n +=1
编辑:
我使用了一些我发现的与LCM有关的代码,并使用reduce来解决问题:
def lcm(*values):
values = [value for value in values]
if values:
n = max(values)
m = n
values.remove(n)
while any( n % value for value in values ):
n +=m
return n
return 0
print reduce(lcm, range(1,21))
答案 0 :(得分:21)
如果问题很难,请尝试解决更简单的版本。这里,如何计算两个数字的最低公倍数。如果你已经读过任何数论理论书(或者考虑素数因子),你可以使用最大公约数函数(由欧几里德算法实现)来做到这一点。
from fractions import gcd
def lcm(a,b):
"Calculate the lowest common multiple of two integers a and b"
return a*b//gcd(a,b)
观察lcm(a,b,c) ≡ lcm(lcm(a,b),c)
使用Python reduce
函数解决问题很简单
>>> from functools import reduce
>>> reduce(lcm, range(1,10+1))
2520
>>> reduce(lcm, range(1,20+1))
232792560
答案 1 :(得分:4)
你正在进行强力搜索,所以它可以长任意。您应该阅读有关LCM(最少公倍数)的信息,以便编写有效的解决方案。(我认为是232792560
)
答案 2 :(得分:2)
int gcd(int m, int n)
{
int t;
while(n!=0)
{
t=n;
n=m%n;
m=t;
}
return m;
}
#include<stdio.h>
int main()
{
int i,n;
int long long lcm=1;
printf("Enter the range:");
scanf("%d",&n);
for (i=1;i<=n;i++)
{
lcm = (i*lcm)/gcd(i,lcm);
}
printf("smallest multiple : %uL",lcm);
}
答案 3 :(得分:1)
这将为您提供从1到20的数字中的所有因素:
from collections import Counter
def prime_factors(x):
def factor_this(x, factor):
factors = []
while x % factor == 0:
x /= factor
factors.append(factor)
return x, factors
x, factors = factor_this(x, 2)
x, f = factor_this(x, 3)
factors += f
i = 5
while i * i <= x:
for j in (2, 4):
x, f = factor_this(x, i)
factors += f
i += j
if x > 1:
factors.append(x)
return factors
def factors_in_range(x):
result = {}
for i in range(2, x + 1):
p = prime_factors(i)
c = Counter(p)
for k, v in c.items():
n = result.get(k)
if n is None or n < v:
result[k] = v
return result
print factors_in_range(20)
如果将这些数字乘以结果中的次数,则会得到将所有数字从1分为20的最小数字。
import operator
def product(c):
return reduce(operator.__mul__, [k ** v for k, v in c.items()], 1)
c = factors_in_range(20)
print product(c)
答案 4 :(得分:0)
import sys
def smallestDiv(n):
divisors = [x for x in range(1,(n+1))] # get divisors
for i in xrange(2520,sys.maxint,n):
if(all(i%x == 0 for x in divisors)):
return i
print (smallestDiv(20))
我的1.7 GHZ i7需要大约5秒钟
答案 5 :(得分:0)
facList=[2]
prod=1
for i in range(3,1000):
n=i
for j in facList:
if n % j == 0:
n//=j
facList.append(n)
for k in facList:
prod*=k
print(prod)
我尝试了这种方法并将我的时间与Panic上校的答案进行了比较,并且我开始在n = 200而非n = 20时大幅击败他。在我看来,他更优雅,但出于某种原因,我的速度更快。也许对算法运行时有更好理解的人可以解释原因。
答案 6 :(得分:0)
最后一个函数找到可被n整除的最小数字,因为该数字应为阶乘(n)的倍数,所以您需要具有一个计算阶乘的函数(可以通过数学方法完成)
def factoral(n):
if n > 1:
return n * factoral(n - 1)
elif n >= 0:
return 1
else:
return -1
def isMultiple(a, b):
for i in range(1, b):
if a % i != 0:
return False
return True
def EnkucukBul(n):
for i in range(n, factoral(n) + 1, n):
if isMultiple(i, n):
return i
return -1
答案 7 :(得分:0)
我认为Panic上校的答案很棒,但我只是想在不编辑简洁答案的情况下扩大一点。
原始解决方案是:
from fractions import gcd
def lcm(a,b):
"Calculate the lowest common multiple of two integers a and b"
return a*b//gcd(a,b)
>>> from functools import reduce
>>> reduce(lcm, range(1,10+1))
2520
>>> reduce(lcm, range(1,20+1))
232792560
我发现可视化N = 10时的减少量是有帮助的:
res = lcm(lcm(lcm(lcm(lcm(lcm(lcm(lcm(lcm(1, 2), 3), 4), 5), 6), 7), 8), 9), 10)
评估为:
# Evaluates lcm(1, 2)
res = lcm(lcm(lcm(lcm(lcm(lcm(lcm(lcm(lcm(1, 2), 3), 4), 5), 6), 7), 8), 9), 10)
# Evaluates lcm(2, 3)
res = lcm(lcm(lcm(lcm(lcm(lcm(lcm(lcm(2, 3), 4), 5), 6), 7), 8), 9), 10)
# Evaluates lcm(6, 4)
res = lcm(lcm(lcm(lcm(lcm(lcm(lcm(6, 4), 5), 6), 7), 8), 9), 10)
# Evaluates lcm(12, 5)
res = lcm(lcm(lcm(lcm(lcm(lcm(12, 5), 6), 7), 8), 9), 10)
# Evaluates lcm(60, 6)
res = lcm(lcm(lcm(lcm(lcm(60, 6), 7), 8), 9), 10)
# Evaluates lcm(60, 7)
res = lcm(lcm(lcm(lcm(60, 7), 8), 9), 10)
# Evaluates lcm(420, 8)
res = lcm(lcm(lcm(420, 8), 9), 10)
# Evaluates lcm(840, 9)
res = lcm(lcm(840, 9), 10)
# Evaluates lcm(2520, 10)
res = lcm(2520, 10)
print(res)
>>> 2520
以上内容涵盖了正在发生的一切。当我们使用reduce时,我们“将滚动计算应用于列表中的顺序值对”。它是从“由内而外”或在range(1, 20+1)
中从左到右进行的。
我认为在这里指出您作为程序员,不要期望您将答案显而易见或显而易见就非常重要。很多聪明人花了很长时间学习了很多有关素数,最大公因数和最小公倍数等的信息。但是,作为软件工程师,您应该了解数论的基础,gcd,lcm,质数以及如何解决工具包中的问题。同样,每次解决问题时,您都不希望重新发明轮子或从数论中发现问题,但是在开展业务时,您应该在解决问题的工具包中添加工具。