Maestumプログラミング、囲碁、読書の話題この広告は、90日以上更新していないブログに表示しています。Haskell第5章は数独ソルバーの実装を通してHaskell/関数型プログラムの書き方(の一つ)を紹介するというもの。問題をできるだけ宣言的に解くコードを記述して、その後最適化していく。この記事は第一段階の非常に非効率な宣言的コードの説明まで。(=='0')Matrix型は[[a]]のalias。一枚の数独問題(回答前・後を問わず)はGrid型で表現する。Digitのaliasであり、DigitはCharのalias。記入されていないマスは0で表される。[Grid]数独を解く関数solveの定義。問題をGridとして受け取り、正解回答となるGridすべてのリストを返す。completionsとvalidという二つの関数を組み合わせて作る。completions。問題Gridを受け取り、、空のマスに1から9までを当てはめていくことで問題を(間違っていてもいいので)埋めきったすべての(非常に多くの)パターンのGridのリストを返す。validは埋めきったGridが数独のルールに従っているかを判定する。validでフィルタすることで、すべてのパターンから正解例のみを取り出す。Digits]choicesはDigitsのMatrixである問題文から、確定しているマスは要素数1、空のマスは要素数9(1..9)のDigitsのリストのMatrixに変換する。expandはその「各マスが取り得るDigit値を列挙したリストのMatrix」を引数にとり、「各マスの取り得る値の直積集合である『DigitのMatrixのリスト』」を返す。[d]個別のマスに対して、'0'以外ならその値のみ入っているリスト、'0'なら['1'..'9']を返すchoice関数を適用する。......]expandexpandを定義するためにはまずcp関数を定義する。cpで一つ一つの行を「その行が取り得るすべての「9つのDigitのリスト」のリスト」に変換する。それをさらにcpすることで、各行が取り得るすべての値の直積に変換する。それがマスを埋めたGridのパターンすべてを網羅したリストだ。choice)となる。duplicatesの略。各行(rows)、各列(cols)、各3x3の区切り(boxs)にダブった数字がないことが正解の条件である。pnodupsあるリストに同じ要素が二回出てくるかチェックする関数。xs一見O(n2)だがn=9なので気にしない。rowsrowsはあるGridの行のリストを返す関数。[[a]]ではないか?と思っている。idcolscolsはGridの列のリストを返す関数。xss)transposeは私が定義した。本の中ではtranspose関数はなく、直接colsをこの定義にしていた。colsという名前で書くのは(とくに次のboxsでも使う手前)不適当な気がしたのでいったんtransposeという名前で定義してcolsをaliasとした。このtransposeの定義、一番最後のリストを一要素ずつのリストのリストにする、というのを再帰の終了条件にして、そのリストにzipWithで前のリストの要素を付け加えていく。理屈はわかるのだが自前で考えろと言われて書ける気が全くしない・・・boxsboxsは3マスx3マスの各区切りの中の数リストが9つ入ったリストを返す。concatリストを「3つの要素ごとのリスト」のリストに変換する関数がgroup、それを元のリストに戻すのがungroup(実際の処理はただのconcat)。挙動を理解するのがけっこうややこしい関数の組み合わせなので、4x4のMatrixを2x2の区切り内の要素のリストに変換する様を書いてみる。d4]]]中の4つの要素のリストが、2つの要素のリスト二つのリストに変換されている。d4]]]]4x2x2要素のリストのリストのリストだったのが、2x2x2x2のリストx4になっている。d2]の位置が入れ替わった。d4]]]2x2x2x2から4x2x2に。b2と左上にあった数字、次のリストは右上、次は左下、最後は右下、と2x2に分割した各区切りの数字のリスト4つになっていることがわかる。これを3x3の区切りで9x9のGridに適用したのが上記のboxs。結論rowsもcolsもboxsもすべてのリストがvalidならそのGridは数独のルール上正しく記入されていることになる。completionsの戻り値をvalidでフィルタすれば、正しい回答のリストが得られる。(kは数字が知られているマスの数)もの結果を返し、それを一つ一つフィルタしていかなければいけない。現実的に不可能である。次回はこの非常に効率の悪いコードに対しどのような等価な変換を加えていくことで最適化ができるか、というポイントを探っていく。Classのd...なんのこっちゃ。問題1.31SICP1.3.1の問題1.31を解いてみる。)はてなブログをはじめよう!zehnpaardさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。