前回までにすべての関数が作成できました。 後は、これらを集めてプログラミングするだけです。
Raspberry Pi が遅いので、最初に考えた検索のループで毎回 fill_list()を使って行リストを作るのは効率が悪そうです。1回だけ実行して、
f_R1,f_R2,f_R3,f_R4,f_R5,f_R6,f_R7,f_R8,f_R9
に代入することにしました。
更に、3行ずつブロックの検査をして、最後に検索するリスト数を減らしてから、列の検査をすることにしました。
プログラムはこんな感じです。
関数定義の部分は省略しました。
print('Question: ')
print_answer(R1,R2,R3,R4,R5,R6,R7,R8,R9)
# 条件を検査して、結果を出力する。
# fill_list()を使うので行の検査は終了している。
f_R1 = fill_list(R1)
f_R2 = fill_list(R2)
f_R3 = fill_list(R3)
f_R4 = fill_list(R4)
f_R5 = fill_list(R5)
f_R6 = fill_list(R6)
f_R7 = fill_list(R7)
f_R8 = fill_list(R8)
f_R9 = fill_list(R9)
right_b1 = []
for row1 in f_R1:
for row2 in f_R2:
for row3 in f_R3:
if chk_block(row1,row2,row3) == False:
continue
right_b1.append([row1,row2,row3])
print(row1)
print(row2)
print(row3)
print('-'*28)
print(' 1-3 blocks')
right_b2 = []
for row4 in f_R4:
for row5 in f_R5:
for row6 in f_R6:
if chk_block(row4,row5,row6) == False:
continue
right_b2.append([row4,row5,row6])
print(row4)
print(row5)
print(row6)
print('-'*28)
print(' 4-6 blocks')
right_b3 = []
for row7 in f_R7:
for row8 in f_R8:
for row9 in f_R9:
if chk_block(row7,row8,row9) == False:
continue
right_b3.append([row7,row8,row9])
print(row7)
print(row8)
print(row9)
print('-'*28)
print(' 7-9 blocks')
print('Answer: ')
for bk1 in right_b1:
for bk2 in right_b2:
for bk3 in right_b3:
if chk_col(bk1[0],bk1[1],bk1[2],bk2[0],bk2[1],bk2[2],bk3[0],bk3[1],bk3[2]) == False:
continue
# 答えを出力。複数の答えも想定する。
print_answer(bk1[0],bk1[1],bk1[2],bk2[0],bk2[1],bk2[2],bk3[0],bk3[1],bk3[2])
print(' ')
print('=== END ===')
メモリがあふれるかもと思いましたが、それは大丈夫でした。しかし、それでも遅い、最初の答えがでるまで半日、他に答えがないことを調べるため全部の検査にさらに1日くらいかかりました。遅いのでちゃんと動いているか不安になり、3つのブロック検査の途中経過も出力してあります。特に2段目(4-6 blocks) の処理が長かったです。
python3 sudoku.py
Question:
0 9 8 | 0 0 6 | 0 0 4
1 0 4 | 0 0 2 | 0 3 0
3 6 7 | 0 0 1 | 0 0 0
------+-------+-------
0 0 0 | 1 0 0 | 4 9 7
0 0 0 | 0 3 0 | 0 0 0
7 4 2 | 0 0 8 | 0 0 0
------+-------+-------
0 0 0 | 2 0 0 | 9 7 6
0 7 0 | 6 0 0 | 5 0 8
6 0 0 | 5 0 0 | 3 4 0
(途中省略)
[6, 9, 1, 5, 7, 8, 3, 4, 2]
----------------------------
[8, 5, 4, 2, 3, 1, 9, 7, 6]
[3, 7, 2, 6, 9, 4, 5, 1, 8]
[6, 9, 1, 5, 8, 7, 3, 4, 2]
----------------------------
7-9 blocks
Answer:
2 9 8 | 3 5 6 | 7 1 4
1 5 4 | 8 7 2 | 6 3 9
3 6 7 | 4 9 1 | 2 8 5
------+-------+-------
8 3 6 | 1 2 5 | 4 9 7
9 1 5 | 7 3 4 | 8 6 2
7 4 2 | 9 6 8 | 1 5 3
------+-------+-------
5 8 1 | 2 4 3 | 9 7 6
4 7 3 | 6 1 9 | 5 2 8
6 2 9 | 5 8 7 | 3 4 1
=== END ===
$
入門なので、自分で作る関数作成はなるべく単純にしてみました。そんなわけで同じ事を3回も繰り返したりして無駄に長くなっているかもしれませんが、後で分かりやすい事を優先しました。
生成AIも要所で使うことにして、2つの関数生成に使う事ができました。どれを生成AIに任せてどれを自分で作るかは色々と試す必要がありそうです。生成AIの回答の関数は入門者には勉強になる部分も多かったので、ちょっと関数を作るときに気になる事があるなら使って良いのかもしれませんね。途中怪しげなプログラムを提示されました、そこは、回答の通りテストする必要があるわけです。Google Gemini の場合は説明が良いですね。docstring 作成に使った方が良いような気がするのは以前書いた通りでした。
プロンプトに一言も入れていないのに「数独でしょ」と言ってどこかから持ってきた関数を提示するのも面白かったです。
入門者には、生成AIを関数生成とかclass定義とかで活用して、得られたものをテストしたり、その中で知らない機能を使っていたら調べたりする事が経験値を上げるには役立ちそうです。今後生成AIが「この関数はこっちの方が良いですよ。」と言ってくる事は当然ありそうなので、活用したいところです。
Raspberry Pi なので、遅いからスピードアップのために改良するという試行錯誤ができるので、Python入門時には何かと役立ちそうです。
Raspberry Pi が遅いので、最初に考えた検索のループで毎回 fill_list()を使って行リストを作るのは効率が悪そうです。1回だけ実行して、
f_R1,f_R2,f_R3,f_R4,f_R5,f_R6,f_R7,f_R8,f_R9
に代入することにしました。
更に、3行ずつブロックの検査をして、最後に検索するリスト数を減らしてから、列の検査をすることにしました。
プログラムはこんな感じです。
関数定義の部分は省略しました。
print('Question: ')
print_answer(R1,R2,R3,R4,R5,R6,R7,R8,R9)
# 条件を検査して、結果を出力する。
# fill_list()を使うので行の検査は終了している。
f_R1 = fill_list(R1)
f_R2 = fill_list(R2)
f_R3 = fill_list(R3)
f_R4 = fill_list(R4)
f_R5 = fill_list(R5)
f_R6 = fill_list(R6)
f_R7 = fill_list(R7)
f_R8 = fill_list(R8)
f_R9 = fill_list(R9)
right_b1 = []
for row1 in f_R1:
for row2 in f_R2:
for row3 in f_R3:
if chk_block(row1,row2,row3) == False:
continue
right_b1.append([row1,row2,row3])
print(row1)
print(row2)
print(row3)
print('-'*28)
print(' 1-3 blocks')
right_b2 = []
for row4 in f_R4:
for row5 in f_R5:
for row6 in f_R6:
if chk_block(row4,row5,row6) == False:
continue
right_b2.append([row4,row5,row6])
print(row4)
print(row5)
print(row6)
print('-'*28)
print(' 4-6 blocks')
right_b3 = []
for row7 in f_R7:
for row8 in f_R8:
for row9 in f_R9:
if chk_block(row7,row8,row9) == False:
continue
right_b3.append([row7,row8,row9])
print(row7)
print(row8)
print(row9)
print('-'*28)
print(' 7-9 blocks')
print('Answer: ')
for bk1 in right_b1:
for bk2 in right_b2:
for bk3 in right_b3:
if chk_col(bk1[0],bk1[1],bk1[2],bk2[0],bk2[1],bk2[2],bk3[0],bk3[1],bk3[2]) == False:
continue
# 答えを出力。複数の答えも想定する。
print_answer(bk1[0],bk1[1],bk1[2],bk2[0],bk2[1],bk2[2],bk3[0],bk3[1],bk3[2])
print(' ')
print('=== END ===')
メモリがあふれるかもと思いましたが、それは大丈夫でした。しかし、それでも遅い、最初の答えがでるまで半日、他に答えがないことを調べるため全部の検査にさらに1日くらいかかりました。遅いのでちゃんと動いているか不安になり、3つのブロック検査の途中経過も出力してあります。特に2段目(4-6 blocks) の処理が長かったです。
python3 sudoku.py
Question:
0 9 8 | 0 0 6 | 0 0 4
1 0 4 | 0 0 2 | 0 3 0
3 6 7 | 0 0 1 | 0 0 0
------+-------+-------
0 0 0 | 1 0 0 | 4 9 7
0 0 0 | 0 3 0 | 0 0 0
7 4 2 | 0 0 8 | 0 0 0
------+-------+-------
0 0 0 | 2 0 0 | 9 7 6
0 7 0 | 6 0 0 | 5 0 8
6 0 0 | 5 0 0 | 3 4 0
(途中省略)
[6, 9, 1, 5, 7, 8, 3, 4, 2]
----------------------------
[8, 5, 4, 2, 3, 1, 9, 7, 6]
[3, 7, 2, 6, 9, 4, 5, 1, 8]
[6, 9, 1, 5, 8, 7, 3, 4, 2]
----------------------------
7-9 blocks
Answer:
2 9 8 | 3 5 6 | 7 1 4
1 5 4 | 8 7 2 | 6 3 9
3 6 7 | 4 9 1 | 2 8 5
------+-------+-------
8 3 6 | 1 2 5 | 4 9 7
9 1 5 | 7 3 4 | 8 6 2
7 4 2 | 9 6 8 | 1 5 3
------+-------+-------
5 8 1 | 2 4 3 | 9 7 6
4 7 3 | 6 1 9 | 5 2 8
6 2 9 | 5 8 7 | 3 4 1
=== END ===
$
入門なので、自分で作る関数作成はなるべく単純にしてみました。そんなわけで同じ事を3回も繰り返したりして無駄に長くなっているかもしれませんが、後で分かりやすい事を優先しました。
生成AIも要所で使うことにして、2つの関数生成に使う事ができました。どれを生成AIに任せてどれを自分で作るかは色々と試す必要がありそうです。生成AIの回答の関数は入門者には勉強になる部分も多かったので、ちょっと関数を作るときに気になる事があるなら使って良いのかもしれませんね。途中怪しげなプログラムを提示されました、そこは、回答の通りテストする必要があるわけです。Google Gemini の場合は説明が良いですね。docstring 作成に使った方が良いような気がするのは以前書いた通りでした。
プロンプトに一言も入れていないのに「数独でしょ」と言ってどこかから持ってきた関数を提示するのも面白かったです。
入門者には、生成AIを関数生成とかclass定義とかで活用して、得られたものをテストしたり、その中で知らない機能を使っていたら調べたりする事が経験値を上げるには役立ちそうです。今後生成AIが「この関数はこっちの方が良いですよ。」と言ってくる事は当然ありそうなので、活用したいところです。
Raspberry Pi なので、遅いからスピードアップのために改良するという試行錯誤ができるので、Python入門時には何かと役立ちそうです。