はじめに
皆様は数独を知っていますか.よく新聞とか雑誌に問題がのっていますね.私は,数独は好きなのですが,どうも苦手で解けないこともしばしばあります.しかしながら,$\texttt{SageMath}$という言語を使えば一瞬で解けてしまうそうです.それでは,$\texttt{SageMath}$を使って数独を解いてみましょう.
SageMathのインストール
まずは,$\texttt{SageMath}$が入ってなければ仕方ありません.そこで,まずインストールの方法を紹介します.
オンラインでインストールすることなく$\texttt{SageMath}$を動かすことができるSage Cell Serverというサイトもありますので,もうインストールしているよという方や,インストールなんてしたくないという方は,Sage Cell Serverを使うと便利です.
SageMathのインストール
$ sudo apt install sagemath
数独を解いてみる
wikipediaの数独のページの例題で解いてみましょう.
sudoku.sage
# 空白は0にして行列の形式で数独を表現する
A = matrix(ZZ, [
[5, 3, 0, 0, 7, 0, 0, 0, 0],
[6, 0, 0, 1, 9, 5, 0, 0, 0],
[0, 9, 8, 0, 0, 0, 0, 6, 0],
[8, 0, 0, 0, 6, 0, 0, 0, 3],
[4, 0, 0, 8, 0, 3, 0 ,0, 1],
[7, 0, 0, 0, 2, 0, 0, 0, 6],
[0, 6, 0, 0, 0, 0, 2, 8, 0],
[0, 0, 0, 4, 1, 9, 0, 0, 5],
[0, 0, 0, 0, 8, 0, 0, 7, 9]
])
# Sudoku関数で数独形式に変換
A = Sudoku(A)
# next(A.solve())で数独を解くことができる
A = next(A.solve())
print(A)
これを実行すると以下のようになります.
$ time sage sudoku.sage
+-----+-----+-----+
|5 3 4|6 7 8|9 1 2|
|6 7 2|1 9 5|3 4 8|
|1 9 8|3 4 2|5 6 7|
+-----+-----+-----+
|8 5 9|7 6 1|4 2 3|
|4 2 6|8 5 3|7 9 1|
|7 1 3|9 2 4|8 5 6|
+-----+-----+-----+
|9 6 1|5 3 7|2 8 4|
|2 8 7|4 1 9|6 3 5|
|3 4 5|2 8 6|1 7 9|
+-----+-----+-----+
real 0m0.912s
user 0m0.731s
sys 0m0.083s
何と,一秒未満で数独を解くことができました.
標準入力から問題を入力しやすくする
sudoku2.sage
def main():
A = matrix(ZZ, 9, 9)
# 標準入力から数独を取得
for i in xsrange(9):
string = input()
for j in xsrange(len(string)):
if string[j] == '0' or string[j] == ' ':
A[i, j] = 0
else:
A[i, j] = ZZ(string[j])
# Sudoku関数で数独形式に変換
A = Sudoku(A)
# 数独を解いて行列形式に変換
print(next(A.solve()))
if __name__ == '__main__':
main()
先ほどと同じ例を解かせてみましょう.
標準入力
53 7
6 195
98 6
8 6 3
4 8 3 1
7 2 6
6 28
419 5
8 79
出力結果
+-----+-----+-----+
|5 3 4|6 7 8|9 1 2|
|6 7 2|1 9 5|3 4 8|
|1 9 8|3 4 2|5 6 7|
+-----+-----+-----+
|8 5 9|7 6 1|4 2 3|
|4 2 6|8 5 3|7 9 1|
|7 1 3|9 2 4|8 5 6|
+-----+-----+-----+
|9 6 1|5 3 7|2 8 4|
|2 8 7|4 1 9|6 3 5|
|3 4 5|2 8 6|1 7 9|
+-----+-----+-----+
また,AtCoderのコードテストで実行させたのですが,実行時間は736msと,2秒は下回っていました.なので,もし数独の問題がでたらめちゃくちゃ楽ができそうです(出力の形式は適宜整える必要がありますが).