How would you program this?

Bill Mill bill.mill at gmail.com
Wed Mar 2 20:51:31 CET 2005


On Wed, 02 Mar 2005 10:23:33 -0800, engsol <engsolnorm at peak.org> wrote:
> There is a number puzzle which appears in the daily paper.
> Because I'm between Python projects, I thought it might be
> fun to write a program to solve it....20 minute job, max.
> 
> On closer inspection, it became apparent that it's not a
> simple thing to program. How would you approach it?
> 
> The puzzle: a 4 x 4 grid. The rows are summed (and given), the
> cols are summed (and given), and the two diagonals are summed,
> and given. In addition, 4 clues are given, but none of the 4 are in
> the same row or col.
> 
> Example from today's paper:...solution time is 8 minutes, 1 second,
> so they say.
> 
> The set of allowable numbers  is 1 thru 9
> 
> Rows:
> 3 + B + C + D = 22
> E + F + 8 + H = 26
> I + J + K + 8 = 31
> M + 7 + O + P = 25
> 
> Col sums:
> 24, 18, 31, 31
> 
> Diag sums:
> 3 + F + K + P = 24
> M + J + 8 + D = 24
> 
> The first impulse is to just brute force it with nested for loops,
> but the calculator shows the possible combinations are
> 9^12 = 5,159,780,352, which would take much too long.
> 

Are you sure about that? You can eliminate a whole lot of options just
based on the row (or column, if you're so inclined) totals. Here's
what I came up with in 10 minutes:

#--------------------linalg_brute.py------------------------------
ns = range(1,10)
def mkrow(limit):
    return [(a,b,c) for a in ns for b in ns for c in ns if a + b + c == limit]
row1 = mkrow(19)
row2 = mkrow(18)
row3 = mkrow(23)
row4 = mkrow(18)
for b,c,d in row1:
    for e,f,h in row2:
        for i,j,k in row3:
            for m,o,p in row4:
                if 3 + e + i + m == 24 and 7 + b + f + j == 18 \
                and 8 + c + k + o == 31 and 8 + d + h + p == 31 \
                and 3 + f + k + p == 24 and m + j + 8 + d == 24:
                    print 3,b,c,d
                    print e,f,8,h
                    print i,j,k,8
                    print m,7,o,p
                    print '-------------'
#--------------end linalg_brute.py-----------------------------

Of course, it could use a whole bunch of generalization, but that
wasn't the point. It runs quite nicely:

02:42 PM /d/code/Python$ time python linalg.py
3 3 8 8
9 3 8 6
9 5 9 8
3 7 6 9
-------------
3 3 9 7
8 3 8 7
9 5 9 8
4 7 5 9
-------------

real    0m1.255s
user    0m1.221s
sys     0m0.030s

Both solutions look correct to me; how about you? With clever enough
heuristics, problems that you can expect people to solve will almost
always fall to brute force algorithms, I feel.

Peace
Bill Mill
bill.mill at gmail.com



More information about the Python-list mailing list