Comment

Comment by joshcorbin

An alternative using Python's builtin monadic machinery (comprehensions) with a utility function to aid with threading around the remaining alphabet:

    def to_number(*digits):
        return sum(d * 10 ** n
                   for n, d in enumerate(reversed(digits)))


    def choose1(digits, *exclude):
        for digit in digits.difference(exclude):
            yield digit, digits - {digit}

    all_digits = set(range(10))

    print [
        (send, more, money)
        for s, e, n, d, send, digits in (
            (s, e, n, d, to_number(s, e, n, d), digits)
            for s, digits in choose1(all_digits, 0)
            for e, digits in choose1(digits)
            for n, digits in choose1(digits)
            for d, digits in choose1(digits))
        for m, o, r, more, digits in (
            (m, o, r, to_number(m, o, r, e), digits)
            for m, digits in choose1(digits, 0)
            for o, digits in choose1(digits)
            for r, digits in choose1(digits))
        for y, money, digits in (
            (y, to_number(m, o, n, e, y), digits)
            for y, digits in choose1(digits))
        if send + more == money]
I could've actually had the base alphabet called `digits`, but found calling it `all_digits` perhaps less confusing so then `digits` is the one that's only internally visible in the comprehension. This solution is lazy internally, then eagerly pumped to full exhaustion; usually changing the outer `[...]` to `next(...)` is more useful.

I find it very useful to remember that comprehensions deeply connected to monads: https://en.wikipedia.org/wiki/Monad_(functional_programming)...

parent joshcorbin 11 years ago

Discussion

Live from the official Hacker News API

A modern reader for Hacker News · SvelteKit + Skeleton