Project Euler 166

プロジェクトオイラー
http://projecteuler.net/index.php

Q166.
4×4のマス目に0〜9を置いて、縦・横・斜めの和がそれぞれ等しくなる場合の数。

まず、4隅に数字を置く。そして、あと5つ数字を置けばマス目が埋まってすべて等しくなるかが判定できる。4隅は、左上 < 右上 < 左下 左上 < 右下 となるようにし、あとは対象性で同じパターンがいくつあるか数える。これがちょっとややこしい。



from itertools import product

def sym(a, b, c, d):
if a == b:
if a == c:
if a == d:
return 1
else:
return 1
else:
if a == d:
return 3
elif c == d:
return 4
elif c < d:
return 8
else:
return 0
else:
if b == c:
if c == d:
return 4
elif a == d:
return 2
else:
return 4
else:
if c == d:
return 8
elif a == d:
return 4
else:
return 8

D = 10
E = D - 1
counter = 0
for a11 in range(D):
for a14 in range(a11, D):
for a41 in range(a14, D):
for a44 in range(a11, D):
n = 0
for a12, a13, a21, a22, a23 in product(range(D), repeat=5):
s = a11 + a12 + a13 + a14

a24 = s - a21 - a22 - a23
if a24 < 0 or E < a24:
continue
a31 = s - a11 - a21 - a41
if a31 < 0 or E < a31:
continue
a32 = s - a14 - a23 - a41
if a32 < 0 or E < a32:
continue
a33 = s - a11 - a22 - a44
if a33 < 0 or E < a33:
continue
a34 = s - a31 - a32 - a33
if a14 + a24 + a34 + a44 != s:
continue
if a34 < 0 or E < a34:
continue
a42 = s - a12 - a22 - a32
if a42 < 0 or E < a42:
continue
a43 = s - a13 - a23 - a33
if a41 + a42 + a43 + a44 != s:
continue
if a43 < 0 or E < a43:
continue

n += 1
counter += n * sym(a11, a14, a41, a44)
print counter