此程序是使用递归和图形着色读取和求解数独棋盘的一种尝试。
type vertex = int * int
module Vertex = Map.Make(struct
type t = vertex
let compare = Stdlib.compare
end)
let ascii_digit c = Char.code c - Char.code '0'
let read_matrix chan =
let rec loop i j grid =
match input_char chan with
| exception End_of_file -> grid
| '\n' -> loop (i+1) 0 grid
| '0'..'9' as c ->
loop i (j+1) @@
Vertex.add (i,j) (ascii_digit c) grid
| _ -> invalid_arg "invalid input" in
loop 0 0 Vertex.empty
let matrix_from_file file =
let chan = open_in file in
let r = read_matrix chan in
close_in chan;
r
(*Print grid method*)
let print_vertex vertex =
let print_node (x,y) g =
Printf.printf "\n(%d, %d) = " x y;
print_int g
in
Vertex.iter print_node vertex
(*Print pretty sudoku*)
let print_board vertex =
let print_node (_x,_y) _grid =
if _y = 0 then
Printf.printf "\n | ";
print_int _grid;
print_string " | "
in
Vertex.iter print_node vertex我正在尝试实现这个fold_neighbours,但是我无法用我的(Map.Vertex)来实现它。我认为我的逻辑是正确的,但是得到了很多错误等等。也许我应该把这些功能分解成单独的功能?
let fold_neighbours v gamma game =
let in_quadrant (x1, y1) (x2, y2) =
x1/3 = x2/3 && y1/3 = y2/3
in
let is_neighbour v n =
in_quadrant v n || fst v = fst n || snd v = snd n
in
let filter v gamma =
if is_neighbour neigh v' then
f v' g' a
else
a
in
fold_vertices filter game发布于 2021-09-07 23:10:11
这比你想象的要容易得多。为了更简单,让我们将任务拆分成简单的子任务,这样我们就不会出错。首先,让我们定义一下邻居是什么。为了让事情更直观,让我们用指南针方向来表示位置(如果你觉得更容易理解,我们可以使用向上和向下)
let north (x,y) = (x+1,y) (* [north p] is to the north of [p] *)
let northeast (x,y) = (x+1,y+1) (* [north p] is to the north of [p] *)
...
let south (x,y) = (x-1,y) (* [north p] is to the north of [p] *)
...
let norhtwest (x,y) = (x-1,y+1) (* [north p] is to the north of [p] *)现在,我们可以说邻居的集合是,
let neighbors p = [
north p;
northeast p;
...
northwest p;
]我们可以写一个函数,取一个顶点和游戏地图,然后折叠到所有可用的邻居上,
let fold_neighbors vertex map ~init ~f =
let visit s v = match Vertex.find_opt v map with
| None -> s
| Some d -> f v d s in
List.fold_left visit init (neighbors vertex)注意,我向访问函数f传递了三个参数:邻居坐标、游戏中顶点的值和状态。
最后一点。您可能会发现,以这种声明性方式定义邻居列表是不符合编程要求的。当然,也可以编写一个函数来生成这八个顶点。为此,我们将使用生成递归。这通常很难推理,但为了学习,让我们试一试,这是我的观点,
let neighbors (x,y) =
let rec gen i j =
if i = 0 && j = 0 then gen (i+1) j
else if i < 2 then (x+i,y+j) :: gen (i+1) j
else if j < 1 then gen (-1) (j+1)
else [] in
gen (-1) (-1)嗯,看起来很难看,但很管用。可以写得更好吗?尝试一下,用更好的版本更新我的答案!:)
https://stackoverflow.com/questions/69044124
复制相似问题