院卒新人サラリーマンのメモ代わり

備忘としてのメモを記載

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)));
/* こういうところは合成関数を使うとスマートになるんだろね */