Search code examples
pythonproductpython-itertools

Python Itertools: Complex "product"


1+3+9 = 13 = 1+3 = 4.
6+1+1+5 = 13 = 1+3 = 4.
9+9+4 = 22 = 2+2 = 4.
etc

Considering the previous examples, one could say that the possibilities of reduction to the number 4 goes up to infinity. Nevertheless, IT IS possible to control the number of digits that enters in the initial game of sums.

def reduct(length):
    ...
    ...
    return reduction

Do you guys have any Idea of how I could code a function like this? I want to input a "length", and, supposing it to be 7 for example, and supposing that the ending reduction is 5, I want it to do this:

x+x+x+x+x+x+x = 5.

Where it gives me ALL THE POSSIBILITIES for the x numbers.

I've spent too much time trying to solve the problem and I could not figure out how to do it. It's a very nice programming exercise by the way (A good challenge); I thank you all very much for the help.


Solution

  • I managed to conjure up a solution (assuming itertools has already been imported):

    def reduct(length, n=5):
        return [i for i in \
                itertools.combinations_with_replacement(range(1, 10), length) \
                if ((sum(i) - 1) % 9 + 1) == n]
    

    This returns all unique combinations that "reduce" to n, which is 5 by default.


    Explanation:

    • itertools.combinations_with_replacement(range(1, 10), length) yields all unique combinations of length one digit numbers (excluding 0). See the documentation.
    • ((sum(i) - 1) % 9 + 1) yields the "reduction" of each combination. It uses the digital root formula ((n - 1) % 9 + 1, with n as the sum of the numbers in the combination.
    • The rest is self explanatory (I hope).

    Some test runs:

    >>> reduct(2)
    [(1, 4), (2, 3), (5, 9), (6, 8), (7, 7)]
    >>> reduct(3)
    [(1, 1, 3), (1, 2, 2), (1, 4, 9), (1, 5, 8), (1, 6, 7), (2, 3, 9),
     (2, 4, 8), (2, 5, 7), (2, 6, 6), (3, 3, 8), (3, 4, 7), (3, 5, 6),
     (4, 4, 6), (4, 5, 5), (5, 9, 9), (6, 8, 9), (7, 7, 9), (7, 8, 8)]
    >>> len(reduct(7))
    715
    

    Specifying a custom n:

    >>> reduct(2, 8)
    [(1, 7), (2, 6), (3, 5), (4, 4), (8, 9)]
    >>> reduct(3, 8)
    [(1, 1, 6), (1, 2, 5), (1, 3, 4), (1, 7, 9), (1, 8, 8), (2, 2, 4),
     (2, 3, 3), (2, 6, 9), (2, 7, 8), (3, 5, 9), (3, 6, 8), (3, 7, 7),
     (4, 4, 9), (4, 5, 8), (4, 6, 7), (5, 5, 7), (5, 6, 6), (8, 9, 9)]
    >>> len(reduct(7, 8))
    715