python icon indicating copy to clipboard operation
python copied to clipboard

[Sum of Multiples] Add Approaches

Open MatthijsBlom opened this issue 2 years ago • 4 comments

MatthijsBlom avatar Mar 24 '23 22:03 MatthijsBlom

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()))

MatthijsBlom avatar Apr 11 '23 15:04 MatthijsBlom

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! 😄

BethanyG avatar Apr 11 '23 15:04 BethanyG

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)
    )

MatthijsBlom avatar Apr 11 '23 17:04 MatthijsBlom

@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.

MatthijsBlom avatar Apr 12 '23 09:04 MatthijsBlom