前回、juliaでSudokuの解法について記事を書きました。
まだ読んでない方は、こちらの記事をどうぞ
さて今回は、おまけとして、複数の問題を読み込んで一気に解いてくれるように改造していきます。
コマンドラインから、問題ファイルの複数送って、それの解答ファイルを出力するプログラムにします。
ファイル入出力
今回、Sudokuのデータは、CSV形式で読み込んで、答えをCSV形式で出力します。
問題CSVファイルの入力
CSVファイルは、DataFrameで読み込んで、それとMatrixに変換して使います。
こんな、ヘッダーなしのSudokuの問題をCSV形式ファイルで作ります。
読み込むときにヘッダーなし(;header=false)の設定で読み込みます。
grid = Matrix(CSV.read("que.csv",DataFrame;header=false))
解答CSVファイルの出力
次にできた答えを出力します。
CSV.write("ans.csv",DataFrame(grid,:auto);header=false))
一度、MatrixをDataFrameに変換してから、CSVファイルに出力します。MatrixをDataFrameに変換するときに、カラム名がないので、自動でつけます。
ヘッダーはいらないのでfalseで
コマンドライン引数
今回は、コマンドラインから実行できるようにするので、コマンドライン引数を取り扱います。
Juliaでコマンドライン引数は、ARGSに格納されています。
例えば、q1.csv q2.csvの二つをコマンドラインから渡すと、ARGSの中には、インデックス付きで格納されています。
>julia sudoku.jl q1.csv q2.csv
ARGS[1]; q1.csv
ARGS[2]; q2.csv
順番に取り出すには、Forループで取り出していきます。
for (i,f) enumerate(ARGS)
print(i)
println(f)
end
enumerate()は、インデックス番号を返してくれます。
これを実行するとこうなります。
1q1.jl
2q2.jl
複数のSudokuを解いて出力するプログラム
ファイル入出力とコマンドライン引数ができたので、実際に解くプログラムを作りましょう。
sudoku関数を作る
ファイル名を受け取って数独を解く関数を作ります。
数独を実際に解くアルゴリズムは、前回実装しました。その時の関数がsolv()でした。これに順次データを送って、解いていく関数を作ります。
function sudoku(i,f)
grid = Matrix(CSV.read("que.csv",DataFrame;header=false))
solv(0,0,grid)
CSV.write("ans$(i).csv",DataFrame(grid,:auto);header=false)
end
流れは、最初にファイル名を読み込む、solv()に問題データを渡して解く、最後にCSV出力を行う
今回は複数解くのでインデックス番号:iとファイル名:fを受け取る関数にしています。
出力部分の”ans$(i).csv”でans1.csv,ans2.csvみたいなインデックス番号付きのファイル名を出力できます。
コマンドライン引数を展開するループ
関数ができたので、関数を実際に呼び出すメイン部分を作ります。
for (i,f) in enumerate(ARGS)
sudoku(i,f)
end
単純にARGSを一つずつ展開して、インデックス番号とファイル名を先ほど作ったsudoku関数に渡します。
実行方法
ここまでプログラムができたので、これをsudoku.jlという名前で保存しましょう。
コマンドラインから次のように実行します。
>julia sudoku.jl q1.csv q2.csv
ans1.csv,ans2.csvが同一フォルダ内に生成されます。
まとめ
今回は、コマンドライン引数を使って、CSVファイルで作ったSudoku問題を複数解けるようにしました。
コマンドライン引数を使えば、ファイル名を渡したり、パラメーターを渡したりして、juliaのREPLに入ったり、jupyterを起動せずに、処理が行えるようになります。
コメント