我有以下代码:
import math
print "Hey, lets solve Task 4 :)"
number1 = input ("How many digits do you want to look at? ")
number2 = input ("What would you like the digits to add up to? ")
final = []
if number1 == 1:
cow = range(1,10)
elif number1 == 2:
cow = range(10,100)
elif number1 == 3:
cow = range(001,1000)
elif number1 == 4:
cow = range(1000,10000)
elif number1 == 5:
cow = range(10000,100000)
elif number1 == 6:
cow = range(100000,1000000)
elif number1 == 7:
cow = range(1000000,10000000)
elif number1 == 8:
cow = range(10000000,100000000)
elif number1 == 9:
cow = range(100000000,1000000000)
elif number1 == 10:
cow = range(1000000000,10000000000)
number3 = cow[-1] + 1
number10 = number3
number8 = number3 - 1
if number1 == 1:
test = range(1,number10)
elif number1 == 2:
test = range(00,number10)
elif number1 == 3:
test = range(000,number10)
elif number1 == 4:
test = range(0000,number10)
elif number1 == 5:
test = range(00000,number10)
elif number1 == 6:
test = range(000000,number10)
elif number1 == 7:
test = range(0000000,number10)
elif number1 == 8:
test = range(00000000,number10)
elif number1 == 9:
test = range(000000000,number10)
elif number1 == 10:
test = range(0000000000,number10)
if number1 == 1:
number7 = number8
elif number1 == 2:
number7 = number8 + 1
elif number1 == 3:
number7 = number8 + 1
elif number1 == 4:
number7 = number8 + 1
elif number1 == 5:
number7 = number8 + 1
elif number1 == 6:
number7 = number8 + 1
elif number1 == 7:
number7 = number8 + 1
elif number1 == 8:
number7 = number8 + 1
elif number1 == 9:
number7 = number8 + 1
elif number1 == 10:
number7 = number8 + 1
n = 0
while n < number7:
a = test[n]
a = str(a)
print a
number4 = sum(int(x) for x in a)
if number4 == number2:
final.append(number4)
n = n + 1
print len(final)
基本上,此代码计算出有多少位数字包含加起来为某些数字的整数。当它运行时,它会询问您想要多少位数(例如4)以及您希望它们加起来的数字。例如,您可以选择4和18,它将计算1000 - 9999中有多少数字的整数加起来为18(例如4545)。
问题是,最后一个问题询问有多少10位数加到39位。使用这段代码,我的计算机需要很长时间,因为它必须从1一直到最大的10位数。当我试过它时,它撞毁了我的电脑!
有没有办法加快循环?
谢谢!
答案 0 :(得分:2)
你推动计算机太难了,老兄:)计算数万亿这样的数字。
看起来xrange更适合你的情况。
cow = xrange(1000, 10000)
答案 1 :(得分:2)
import math
print "Hey, lets solve Task 4 :)"
number1, number2, answer = 4, 18, 0
for num in xrange(10 ** (number1 - 1), 10 ** number1):
total = 0
while num:
total += num % 10
num /= 10
if total == number2: answer += 1
print answer
答案 2 :(得分:1)
你似乎是用一些强力方法做的,你应该找到一种方法来跳过一些迭代。
例如,您选择4和18,而您的号码是1809:
1809 = 18 # match
1810 = 10
1811 = 11
1812 = 12
有一种模式,你需要优化它以跳过一些迭代。
答案 3 :(得分:1)
你的暴力算法是指数级的,所以无论你如何实现它都会很慢。 aIKid的建议将帮助你避免充斥内存,但它仍然需要很长时间才能运行。
我建议使用另一种增量算法:
number1 = 4
number2 = 18
options={}
for i in range(1,10):
options[i]=1 # for single digit numbers there is one option for each target total
for _ in range(1,number1):
new_options={}
for i in range(0,10): # for each new digit we can add
for option in options: # go through all the options
cur_total=i+option
if cur_total not in new_options:
new_options[cur_total]=0
new_options[cur_total]+=options[option] # and calc how many options this digit add for each target total
options=new_options
print(options[number2])
答案 4 :(得分:1)
当您拥有大数字时,最快的解决方案是根本不会查看单个数字。如果你想知道有多少10位数字总和为39,首先找到所有10位数的独特组合,总和为39(其中2630)。
您可以这样做的方法是为每个数字d
找到所有9位数字的唯一组合,总计39-d,其中没有数字小于d
。
def unique_combos(digits, total, smallest=0):
if digits*9 < total or digits*smallest > total:
return
if digits==1:
yield [total]
return
for i in range(smallest, 10):
for combo in unique_combos(digits-1, total-i, i):
yield [i]+combo
然后,对于每个唯一的数字组合,找出可以安排的方式。这只是简单的数学运算,只有你必须避免计算以前导零开头的任何数字。
import operator
from collections import Counter
from math import factorial
def npermutations(l):
"""From stackoverflow 16453188"""
num = factorial(len(l))
mults = Counter(l).values()
den = reduce(operator.mul, (factorial(v) for v in mults), 1)
return num / den
现在只需将每个组合的数字相加即可得到答案。鉴于我们不再过分担心速度,我只是用较少的数字减去数字。
def answer(digits, total):
n_or_fewer = sum(npermutations(l) for l in unique_combos(digits, total))
fewer = sum(npermutations(l) for l in unique_combos(digits-1, total))
print("There are {} {}-digit numbers with digits summing to {}".format(
n_or_fewer - fewer,
digits, total))
if __name__=='__main__':
answer(4,18)
answer(10,39)
输出时间不到1秒:
C:\Temp>digitsum2.py
There are 615 4-digit numbers with digits summing to 18
There are 307100365 10-digit numbers with digits summing to 39
为了完整起见,Sudipta建议优化您如何逐步完成数字。这里有一些代码可以做到这一点:它直接从一个数字到下一个数字,并获得4位数字的相同答案,但我仍然厌倦了为3.07亿个10位数值运行它。它可能会被优化一点,但蛮力是错误的方式去这里。
def smallest_sum(n, digits, first=1):
"""Find the smallest number with 'digits' digits that sum to 'n'
Returns the value as a list of digits because that's what we need next anyway"""
k = max(first,n + 9 - 9*digits)
assert k <= 9, "Impossible values"
if digits > 1:
return [k]+smallest_sum(n-k, digits-1, 0)
return [k]
def all_sums(digits):
"""Find the next string of digits with the same sum.
We can do this by finding the last non-zero digit and decrementing it
then incrementing the previous non-nine, and sorting any digits that
follow it."""
yield digits
while True:
was = list(digits)
for i in range(len(digits)-1,-1,-1):
if digits[i] != 0:
decrement = i
break
else:
return
for i in range(decrement-1,-1,-1):
if digits[i] != 9:
increment = i
break
else:
return
digits[decrement] -= 1
digits[increment] += 1
if increment < len(digits)-2:
digits[increment+1:] = digits[increment+1:][::-1]
assert digits > was
yield digits
def count(num_digits, total):
try:
digits = smallest_sum(total, num_digits)
except AssertionError:
return 0
return sum(1 for _ in all_sums(digits))
if __name__=='__main__':
print(count(4,18))
print(count(10,39))
答案 5 :(得分:0)
首先,正如许多其他答案所表明的那样:你需要使用xrange
,它就像一个生成器,逐个给你每个数字并节省大量内存。
您还可以通过合并一些优化来改进算法:
检查给定范围内的 min和max 数字,其整数加起来为给定总和。
示例 - 您的号码是4和18.您可以运行1089到9900的循环,而不是检查所有号码。
如果找到匹配项,则紧接着的下一个数字永远不会匹配(因为它的数字总和将比当前数字多1或8,17 ...比现在少没有。)。同样,即使是下一个也不能使用......依此类推,你可以找到一个模式来安全地跳过这些数字 (另一个答案中提出了类似的策略)
一开始,您可以检查一些边缘情况,例如,如果sum的输入小于9。
示例 - 您的数字是4(数字编号)和5(数字之和)。然后我们可以安全地排除其中包含数字6,7,8,9的所有数字。