問題
1から9の数字を 3×3 に配置し、各行・各列・各対角線の和がいずれも15になるようにせよ。(魔方陣)
回答
example03_magic_square.py
from z3 import *
X = [[Int("x_%s_%s" % (i, j)) for j in range(3)] for i in range(3)]
s = Solver()
s.add([And(1 <= X[i][j], X[i][j] <= 9) for i in range(3) for j in range(3)])
s.add([Distinct([X[i][j] for i in range(3) for j in range(3)])])
s.add([Sum([X[i][j] for i in range(3)]) == 15 for j in range(3)])
s.add([Sum([X[i][j] for j in range(3)]) == 15 for i in range(3)])
s.add([Sum([X[i][i] for i in range(3)]) == 15])
s.add([Sum([X[i][2-i] for i in range(3)]) == 15])
print(s.check())
m = s.model()
for i in range(3):
row = []
for j in range(3):
row.append(m[X[i][j]])
print(row)
出力
sat
[6, 7, 2]
[1, 5, 9]
[8, 3, 4]
解説
Distinct()
は、「入力した変数群は互いに異なる」という制約を生成します。
例)Distinct(x, y, z) → And(Not(x == y), Not(x == z), Not(y == z))
Distinct()の詳細