Solving for E and O

I was helping my 10 year old out with her math homework this evening, and she had been given an interesting series of problems which made you find the difference between two numbers.  Pretty straight forward stuff, except that they specified that each individual digit in each of the three separate numbers (the minuend, the subtrahend, and the difference) should be either even or odd.

This is a lot more challenging!

There was one particular question which everyone was struggling to find an answer for which looked something like this:


‘E’ being an even digit, and ‘O’ being an odd digit. It turns out there are actually 9,000 answers to that, but how do you prove it? Like any normal (former) software engineer, I decided to just brute force it and hack together a solver.  You can save this and run it by passing it three strings of E’s and O’s.

import sys
import itertools

odd = [1, 3, 5, 7, 9]
even = [0, 2, 4, 6, 8]

def compute(minuend, subtrahend, difference):
    def get_nums(template):
        nums = list()
        factor = 1
        for x in reversed(template):
            if x.lower() == 'o':
                nums.append([n*factor for n in odd])
            if x.lower() == 'e':
                nums.append([n*factor for n in even])
            factor \*= 10
        return [sum(n) for n in itertools.product(*nums)
            if len(template) == len('%d' % sum(n))]

     num_a = get_nums(minuend)
     num_b = get_nums(subtrahend)

     nums = list()
     for x in num_a:
         for y in num_b:
             if x < y:
             diff = x - y
             if len('%d' % diff) != len(difference):

             found = True
             for c in difference:
                 if c == 'o' and diff % 2 == 0:
                     found = False
                 elif c == 'e' and diff % 2 == 1:
                     found = False
                 diff /= 10

             if found:
                 nums.append([x, y, x - y])

    for n in nums:
        print "%d - %d = %d" % (n[0], n[1], n[2])

if __name__ == '__main__':
    compute(sys.argv[1], sys.argv[2], sys.argv[3])