Just for fun: Countdown numbers game solver

Paul Rubin http
Mon Jan 21 02:51:41 EST 2008


Arnaud Delobelle <arnodel at googlemail.com> writes:
> After a quick glance at your code it seems to me that you can only
> have solutions of the type:
>         (num, num, op, num, op, num, op, num, op, num, op)
> this omits many possible solutions (see the one above).

Here's my latest, which I think is exhaustive, but it is very slow.
It prints a progress message now and then just to give the user some
sign of life.  It should print a total of 256-8 = 248 of those
messages and it takes around 20 minutes on my old 1 Ghz Pentium 3.  It
does find plenty of solutions for 234, e.g.

   234 mul(9,sub(mul(mul(6,mul(3,1)),7),100))

There are some obvious clunky ways to speed it up through memoizing
and symmetry folding but I can't help thinking there's a concise
elegant way to do that too.

================================================================
    from operator import *
    from time import time, ctime
    start_time = time()

    def partition(k):
        for i in xrange(1, (1<<k) - 1):
            yield tuple(bool(i & (1<<j)) for j in xrange(k))

    ams = [add,mul,sub]

    def countdown(nums, trace='', ops=[add,mul,sub,div]):
        d = div in ops

        if len(nums) == 1:
            yield nums[0], str(nums[0])

        for p1 in partition(len(nums)):
            n0s = list(a for p,a in zip(p1, nums) if p)
            n1s = list(a for p,a in zip(p1, nums) if not p)

            for f in ops:
                if d: print '->', n0s, f, '%.3f'%(time()-start_time)
                for r0,t0 in countdown(n0s, trace, ams):
                    for r1,t1 in countdown(n1s, trace, ams):
                        if f != div or r1 != 0 and r0 % r1 == 0:
                            yield f(r0, r1), \
                                  '%s(%s,%s)'% (f.__name__, t0, t1)

    def find_repr(target, nums):
        for x,t in countdown(nums):
            if x == target:
                print x,t

    print ctime()
    find_repr(234, [100,9,7,6,3,1])



More information about the Python-list mailing list