[Sum of Multiples] Add Approaches
U-oh, yet another approach:
from heapq import heapify, heapreplace
from itertools import takewhile
def sum_of_multiples(limit, factors):
def multiples():
queue = [(_, _) for _ in factors if _ != 0]
heapify(queue)
previous_multiple = 0
while queue:
multiple, factor = queue[0]
if multiple != previous_multiple:
yield multiple
previous_multiple = multiple
heapreplace(queue, (multiple + factor, factor))
return sum(takewhile(lambda n: n < limit, multiples()))
WOOT! I was going to mention that one when you were posting in the forum, and then got distracted and wandered away. Glad you remembered it! 😄
Yesterday or this morning I remembered Eppstein's/Martelli's primes generator (improvements on StackOverflow); the above solution immediately followed.
Yet another approach:
from itertools import combinations
from math import lcm
def sum_of_multiples(limit, factors):
factors = [_ for _ in factors if _ != 0]
def range_sum(d):
# `sum(range(0, limit, d))` but in constant time
q = (limit - 1) // d
return d * q * (q + 1) // 2
return sum(
# inclusion/exclusion
(-1) ** (r - 1) * range_sum(lcm(*fs))
for r, _ in enumerate(factors, start=1)
for fs in combinations(factors, r)
)
@BethanyG Do you still wish for these lambda assignments to be avoided?
My own preference is to revert most of 5dbe577. (I'd like to keep the admonitions.) I could add some more prose on the matter, or lift the deleted paragraph into a exercism/caution, or something.