Last active
May 13, 2024 12:57
-
-
Save wakita/164f2638a411b26dc2664986ef190fa6 to your computer and use it in GitHub Desktop.
SMTソルバーを用いた数独の解
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import numpy as np | |
from z3 import * | |
# 例題 | |
board_spec = ''' | |
39 | |
1 5 | |
3 5 8 | |
8 9 6 | |
7 2 | |
1 4 | |
9 8 5 | |
2 6 | |
4 7 ''' | |
board_spec = np.array([list(row) for row in board_spec.split('\n')[1:]]) | |
board = np.array([Int(f'v{i}') for i in range(9*9)]).reshape((9, 9)) | |
def distinct(M): | |
solver.add(Distinct(M.flatten().tolist())) # 「相異なる」制約 | |
solver = Solver() # SMTソルバーの設定 | |
for ch, v in zip(board_spec.flatten(), board.flatten()): | |
solver.add(And(1 <= v, v <= 9) if ch == ' ' else v == int(ch)) | |
for i in range(9): | |
distinct(board[i,:]) # 各行の値は相異なる | |
distinct(board[:,i]) # 各列の値は相異なる | |
distinct(board[3*(i//3):3*(i//3+1), 3*(i%3):3*(i%3+1)]) # 各3x3ブロックの値は相異なる | |
if solver.check() == sat: | |
model = solver.model() | |
print(np.frompyfunc(lambda v: model[v], 1, 1)(board)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@fuloru169さんのQiitaの記事を参考にさせていただきました。
実行結果は以下です。実行時間のほとんどはライブラリの読み込み時間のような気がします。