この 2 つを理解出来れば良い
This produces all solutions by essentially a backtracking algorithm. The heart is the extends? function, which takes a partial solution for the first k<size columns and sees if the solution can be extended by adding a queen at row n of column k+1. The extend function takes a list of all partial solutions for k columns and produces a list of all partial solutions for k+1 columns. The final list solutions is calculated by starting with the list of 0-column solutions (obviously this is the list [ [] ], and iterates extend for size times.
おおまかに言うと
一つずつ試していく ダメになった時点で大丈夫だった時点まで戻る 次を試す 最後まで行けたものが解であるこの実装の心臓部は extends? 関数である
k (k < size) 列の部分解を受け取りそれに n を付け加えても大丈夫かどうかを調べる
k (k < size) 列,size 行のチェス盤でそれぞれの列に 1 つのクイーンを配置しどの 2 つもお互いに効き合っていないもの
size が 4 とする
k = 0
[]
k = 1
[1] [2] [3] [4]
k = 2
[1 3] [1 4] [2 4] [3 1] [4 1] [4 2]
"n を付け加えても…" とはどういう意味か
n は 1 ≦ n ≦ size を満たす整数である
n を部分解の最後に追加しても新たな部分解になるか?ということ
拡張可能・不可能を判断してみる
size = 4 として以下の部分解を考える
[2 4]
n = 1 を付け加える: OK
[2 4 1]
n = 2 を付け加える: NG
[2 4 2]
n = 3 を付け加える: NG
[2 4 3]
図で見てみる
[2 4] -> [2 4 1]
+-+-+ +-+-+-+ | | | -> | | |Q| +-+-+ +-+-+-+ |Q| | |Q| | | +-+-+ +-+-+-+ | | | | | | | +-+-+ +-+-+-+ | |Q| | |Q| | +-+-+ +-+-+-+
OK
図で見てみる
[2 4] -> [2 4 2]
+-+-+ +-+-+-+ | | | -> | | | | +-+-+ +-+-+-+ |Q| | |Q| |Q| +-+-+ +-+-+-+ | | | | | | | +-+-+ +-+-+-+ | |Q| | |Q| | +-+-+ +-+-+-+
NG
図で見てみる
[2 4] -> [2 4 3]
+-+-+ +-+-+-+ | | | -> | | | | +-+-+ +-+-+-+ |Q| | |Q| | | +-+-+ +-+-+-+ | | | | | |Q| +-+-+ +-+-+-+ | |Q| | |Q| | +-+-+ +-+-+-+
NG
実装
(defn extends? [v n] (let [k (count v)] (not-any? true? (for [i (range k) :let [vi (v i)]] (or (= vi n) ;check for shared row (= (- k i) (Math/abs (- n vi)))))))) ;check for shared diagonal
v が部分解n が拡張する列のクイーンの位置
前回勘違いしていたこと
+-+-+ +-+-+-+ | | | -> | | | | +-+-+ +-+-+-+ | | | | | | | +-+-+ +-+-+-+ | | | | +-+-+-+
こういう形の拡張ではない
部分解の集合から拡張された部分解の集合を得る関数
[[1] [2] [3] [4]]
から
[[1 3] [1 4] [2 4] [3 1] [4 1] [4 2]]
を得る
extend 関数を 8 回適用すれば 8-Queens の解が無事得られる