Hacker News new | ask | show | jobs
by joshcorbin 3968 days ago
Further showing the advantage of the pythonic way, is that the above construction remains about as clear when you refactor it for better pruning:

    (
        (to_number(s, e, n, d),
         to_number(m, o, r, e),
         to_number(m, o, n, e, y))

        for d, digits in choose1(digits)
        for e, digits in choose1(digits)
        for y, digits in choose1(digits)
        if (d + e) % 10 == y

        for n, digits in choose1(digits)
        for r, digits in choose1(digits)
        if (n + r + (d + e) // 10) % 10 == e

        for o, digits in choose1(digits)
        if (e + o + (n + r + (d + e) // 10) // 10) % 10 == n

        for s, digits in choose1(digits, 0)
        for m, digits in choose1(digits, 0)
        if (s + m + (e + o + (n + r + (d + e) // 10) // 10) // 10) % 10 == o
        if (s + m + (e + o + (n + r + (d + e) // 10) // 10) // 10) // 10 == m)
Ends up being several order of magnitudes faster since it partially sums each place and prunes aggressively. You can eliminate the sub-expressions, but it has noise impact on the run time (likely due to trading off temporary tuples for cheap arithmetic):

    (
        (to_number(s, e, n, d),
         to_number(m, o, r, e),
         to_number(m, o, n, e, y))

        for d, digits in choose1(digits)
        for e, digits in choose1(digits)
        for y, digits in choose1(digits)
        if (d + e) % 10 == y

        for n, digits in choose1(digits)
        for r, digits in choose1(digits)
        if (n + r + (d + e) // 10) % 10 == e

        for o, digits in choose1(digits)
        if (e + o + (n + r + (d + e) // 10) // 10) % 10 == n

        for s, digits in choose1(digits, 0)
        for m, digits in choose1(digits, 0)
        if (s + m + (e + o + (n + r + (d + e) // 10) // 10) // 10) % 10 == o
        if (s + m + (e + o + (n + r + (d + e) // 10) // 10) // 10) // 10 == m)