OCAML代码精简咨询:attack与attacked函数的更短实现
简化OCaml中attack和attacked函数的方案
当然可以!咱们来一步步优化这两个函数,让代码更简洁易读,同时贴合OCaml的函数式编程风格。
原代码回顾
先把原代码贴出来方便对比:
let board = [|('a', 1); ('b', 2); ('c', 3); ('d', 4);('e', 5); ('f', 6); ('g', 7); ('h', 8)|];; let int_of_col letter = int_of_char letter-96;; let abs x = if x < 0 then - x else x;; let attack (a,x)(b,y) = ((int_of_col a - int_of_col b)*(x-y)) = 0 || (abs(int_of_col a - int_of_col b) = abs(x-y));; let attacked listing = let out = Array.make 8 false in for i=0 to 7 do for j=0 to 7 do if(i != j) then if(attack listing.(i) listing.(j)) then out.(i) <- true done done; out;;
优化1:简化attack函数
首先,咱们可以去掉单独的int_of_col函数,直接在attack里用标准库的Char.code计算列差,同时把条件拆解得更直观(同列、同行、对角线三种情况):
let attack (a, x) (b, y) = let col_diff = Char.code a - Char.code b in col_diff = 0 || x = y || abs col_diff = abs (x - y)
- 用
Char.code替代自定义的int_of_col,避免了魔法数字96,更符合OCaml惯用写法; - 把原代码中
((col_diff)*(x-y))=0拆成col_diff=0 || x=y,逻辑更清晰,可读性更强; - 原代码里的自定义
abs可以直接替换成OCaml标准库的Stdlib.abs,不用重复实现。
优化2:简化attacked函数
原代码用嵌套for循环修改可变数组,咱们可以用OCaml的函数式工具Array.mapi和Array.existsi来实现,避免可变状态,代码更紧凑:
let attacked queens = Array.mapi (fun i q -> Array.existsi (fun j q' -> j <> i && attack q q') queens ) queens
Array.mapi遍历数组的每个元素和对应索引,帮我们处理每个皇后的位置;Array.existsi检查数组中是否存在满足条件的元素(这里是索引j不等于i,且两个皇后互相攻击);- 完全去掉了可变数组
out的操作,符合函数式编程的无副作用原则,代码更简洁。
整合后的完整代码
把所有优化整合起来,最终代码如下:
let board = [|('a', 1); ('b', 2); ('c', 3); ('d', 4); ('e', 5); ('f', 6); ('g', 7); ('h', 8)|] let attack (a, x) (b, y) = let col_diff = Char.code a - Char.code b in col_diff = 0 || x = y || abs col_diff = abs (x - y) let attacked queens = Array.mapi (fun i q -> Array.existsi (fun j q' -> j <> i && attack q q') queens ) queens
这样代码不仅更简洁,可读性也大大提升,同时保留了原有的功能~
内容的提问来源于stack exchange,提问作者A .45 Enthusiast
相关产品推荐
相关产品推荐

