8クイーン問題 できた!!
やっと8クイーン問題ができた(たぶん)
/* lstの要素すべてがfを満たせばtrue */ /* isSafeでクイーンチェックに使用 */ let rec all = (f, lst) => switch (lst) { | [] => true | [_, ...rest] => f(lst) == true ? all(f, rest) : false }; /* リストを受け取り、リストの先頭と残りでクイーン配置できるかチェック */ /* isSafeで使用、先頭のみだからallで全要素にする */ let checkQueen = lst1 =>{ switch (lst1) { | [] => true | [tar, ...restTar] => let rec aux = (tar, n, lst2) => switch (lst2) { | [] => true | [hd, ...rest] => if (tar == hd + n || tar == hd - n) { false; } else { aux(tar, n + 1, rest); } }; aux(tar, 1, restTar); }; } /* lstを受け取ってクイーンが配置できるかチェック */ let isSafe = el1 => all(checkQueen, el1); /* 作成した順列を8queenの条件でフィルタリング */ let filterQueen = lst => List.filter(isSafe, lst); /* 目的:1から受け取ったnumまでのリストを作る */ /* 順列作成に使用 */ let rec enumerable = num => switch (num) { | 1 => [1] | _ => [num, ...enumerable(num - 1)] }; /* let test1 = enumerable(5) */ /* 目的:与えられたリストの順列を求める */ let rec permutations2 = lst => { let mapcons = (num, lst) => List.map(el => [num, ...el], lst); let rm = (x, l) => List.filter((!=)(x), l); switch (lst) { | [] => [] | [x] => [[x]] /* 要素が一つで下行くと空になっちゃうから再帰が終わらないから*/ | _ => List.fold_left( (acc, cur) => { let removed_rest = rm(cur, lst); /*lstからcurを取り除いたリスト*/ acc @ mapcons(cur, permutations2(removed_rest)); }, [], lst, ) }; }; let test3 = filterQueen(permutations2(enumerable(8))); /* こういうところは合成関数を使うとスマートになるんだろね */