# -*- coding: utf-8 -*-
from typing import Any
from pysimple import Set
[ドキュメント]def showsudoku(Rows: Set, Cols: Set, Vals: Set, table: dict) -> None:
from sys import stdout
for r, in Rows:
if r in (1, 4, 7):
stdout.write("+-------+-------+-------+\n")
for c, in Cols:
for v, in Vals:
if table[v,r,c] == 1:
break
else:
v = ' '
if c in (1, 4, 7):
stdout.write("| ")
stdout.write(str(v) + " ")
stdout.write("|\n")
stdout.write("+-------+-------+-------+\n")
[ドキュメント]def sudoku(**kwds: Any) -> None:
"""数独"""
from pysimple import Problem, Set, Element, BinaryVariable, Sum, Parameter
Vals = Rows = Cols = Set(value=range(1, 10))
v = Element(set=Vals)
r = Element(set=Rows)
c = Element(set=Cols)
Blocks = Set(value=[(s+1, s//3*3+t//3+1, s%3*3+t%3+1) for s in range(9) for t in range(9)])
b = Element(set=Blocks) # b(0) は Block 番号
print(Blocks)
Init = Set(value=[(5, 1, 1), (6, 2, 1), (8, 4, 1), (4, 5, 1), (7, 6, 1), (3, 1, 2), (9, 3, 2), (6, 7, 2), (8, 3, 3), (1, 2, 4), (8, 5, 4), (4, 8, 4), (7, 1, 5), (9, 2, 5), (6, 4, 5), (2, 6, 5), (1, 8, 5), (8, 9, 5), (5, 2, 6), (3, 5, 6), (9, 8, 6), (2, 7, 7), (6, 3, 8), (8, 7, 8), (7, 9, 8), (3, 4, 9), (1, 5, 9), (6, 6, 9), (5, 8, 9), (9, 9, 9)])
init = Element(set=Init)
x = BinaryVariable(index=(v,r,c)) # 値 v が (r,c) に入るか
prob = Problem(name='数独')
prob += Sum(x[v,r,c], v) == 1 # 各マスにはいずれかの値
prob += Sum(x[v,r,c], r) == 1 # 各値は各列のいずれか
prob += Sum(x[v,r,c], c) == 1 # 各値は各行のいずれか
prob += Sum(x[v,b(1,2)], b(1,2)) == 1 # 各値は各ブロックのいずれか
prob += x[init] == 1 # 初期条件
print(prob)
prob.solve(**kwds)
print(x[x[v,r,c].val==1])
inittable = Parameter(index=(v,r,c), value=dict.fromkeys(Init, 1))
resulttable = dict(x.val.items()) # dump as dict
showsudoku(Rows, Cols, Vals, inittable)
showsudoku(Rows, Cols, Vals, resulttable)
PROBLEMS = (sudoku,)
if __name__ == '__main__':
from sys import argv
if argv[1:]:
for arg in argv[1:]:
getattr(__import__(__name__), arg)()
else:
for PROBLEM in PROBLEMS:
PROBLEM()