首先,我为我不准确的词汇道歉。我是一个绝对的零开始。无论如何,我试图解决这个问题: http://projecteuler.net/problem=1
简而言之,我正在尝试编写一个脚本,它将找到低于1000的3或5的所有倍数的总和。
我的(非常基本的)方法是使用这个程序:
##Multiples of 3
x = range(3, 1000, 3)
##Multiples of 5
y = range(5, 1000, 5)
a = sum(x)
b = sum(y)
n = a + b
print n
我意识到这是错误的,因为有15个数字被包含两次(它是5和3的倍数)。 那么有没有办法解决这个问题,还是我从一个完全错误的角度来解决这个问题? 或者在尝试解决此问题之前,我是否需要更多地学习? 如果在之前的帖子中已经解释过这个问题,我也很抱歉,但我看了一下。
答案 0 :(得分:4)
您可以使用set
来消除重复项:
>>> len(x)
333
>>> len(y)
199
>>> s = set(x + y)
>>> len(s)
532
然后你可以sum
代替那些成员。
答案 1 :(得分:4)
它被称为包含排除原则,所以你可以这样做
##Multiples of 3
x = range(3, 1000, 3)
##Multiples of 5
y = range(5, 1000, 5)
##multiple of 15 are counted twice
z=range(15,1000,15)
a = sum(x)
b = sum(y)
c = sum(z)
n = a + b -c
print(n)
但美丽在于使用生成器或列表推导
a = sum(i for i in range(1000) if i%3 == 0 or i%5 == 0 )
print(a)
其中%是modulo并且是整数分割中的余数。 关于这一点的好处是代码读得如此流畅,并且是规则的直接翻译,可以从左到右阅读。
两种算法运行时间取决于n在这种情况下是1000.如果n将是例如1000000000,则必须等待很长时间才能完成。如果你应用小数学,你可以找到
sum(a for a in range(a1,a2,n))
实际上是arithmetic progression,无论n多大,都可以在恒定时间内计算总数。 http://en.wikipedia.org/wiki/Project_Euler#Example_problem_and_solutions
答案 2 :(得分:2)
答案 3 :(得分:1)
您正在寻找sets。
##Multiples of 3
x = range(3, 1000, 3)
##Multiples of 5
y = range(5, 1000, 5)
x = list(set(x) - set(y))
根据您的操作,您必须更改代码。以上内容会移除y
中x
的所有内容。这就像列表,但你可以对项目进行算术运算。
答案 4 :(得分:1)
要合并已排序的序列,您可以使用heapq.merge
:
import heapq
print list(heapq.merge(xrange(3, 20, 3), xrange(5, 20, 5)))
# -> [3, 5, 6, 9, 10, 12, 15, 15, 18]
要删除重复的项目,可以使用unique_justseen
recipe from itertools documentation:
print list(unique_justseen([3, 5, 6, 9, 10, 12, 15, 15, 18]))
# -> [3, 5, 6, 9, 10, 12, 15, 18]
在这种情况下,unique_justseen()
可以简化为:
from itertools import groupby, imap
from operator import itemgetter
def unique_justseen(iterable):
return imap(itemgetter(0), groupby(iterable))
这些函数不需要输入参数作为序列。它们接受任意迭代(包括无限),例如,生成3或5的倍数的无限序列:
import heapq
from itertools import count, takewhile
m3, m5 = count(3, 3), count(5, 5)
m3_5 = heapq.merge(m3, m5)
uniq_m3_5 = unique_justseen(m3_5) # *all* unique multiples of 3 or 5
找到解决方案:
print sum(takewhile(lambda x: x < 1000, uniq_m3_5))
# -> 233168
# check that it is correct
print sum(set(range(3, 1000, 3) + range(5, 1000, 5)))
# -> 233168
print sum(x for x in xrange(1000) if x % 3 == 0 or x % 5 == 0)
# -> 233168
print sumk(3, 1000) + sumk(5, 1000) - sumk(15, 1000)
# -> 233168
sumk()
的位置:
def sumk(k, n):
m = (n-1)//k
return k*m*(m+1)//2
该公式来自the Wikipedia link提供的@ralu。
答案 5 :(得分:0)
我不知道这是否效果不高,但是制作两个集合并对两者进行布尔运算以删除重复项似乎是多余的,因为集合的定义是
所以只需将两个范围添加到一个集合中,然后让“创建”集合删除欺骗:
sum(set(range(3, 1000, 3) + range(5, 1000, 5)))