首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >对于我在Ocaml中关于此问题的fold_neighbours尝试,我需要一些反馈

对于我在Ocaml中关于此问题的fold_neighbours尝试,我需要一些反馈
EN

Stack Overflow用户
提问于 2021-09-03 11:22:54
回答 1查看 156关注 0票数 0

此程序是使用递归和图形着色读取和求解数独棋盘的一种尝试。

代码语言:javascript
复制
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)来实现它。我认为我的逻辑是正确的,但是得到了很多错误等等。也许我应该把这些功能分解成单独的功能?

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2021-09-07 23:10:11

这比你想象的要容易得多。为了更简单,让我们将任务拆分成简单的子任务,这样我们就不会出错。首先,让我们定义一下邻居是什么。为了让事情更直观,让我们用指南针方向来表示位置(如果你觉得更容易理解,我们可以使用向上和向下)

代码语言:javascript
复制
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] *)

现在,我们可以说邻居的集合是,

代码语言:javascript
复制
let neighbors p = [
  north p;
  northeast p;
  ...
  northwest p;
]

我们可以写一个函数,取一个顶点和游戏地图,然后折叠到所有可用的邻居上,

代码语言:javascript
复制
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传递了三个参数:邻居坐标、游戏中顶点的值和状态。

最后一点。您可能会发现,以这种声明性方式定义邻居列表是不符合编程要求的。当然,也可以编写一个函数来生成这八个顶点。为此,我们将使用生成递归。这通常很难推理,但为了学习,让我们试一试,这是我的观点,

代码语言:javascript
复制
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)

嗯,看起来很难看,但很管用。可以写得更好吗?尝试一下,用更好的版本更新我的答案!:)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69044124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档