在矩阵上练习 - Ocaml

时间:2016-12-05 22:00:33

标签: functional-programming ocaml

我目前正在矩阵上练习,但我并不确定以最有效的方式来解决我遇到的一些问题。

我的第一个"问题"是优化功能。我尝试做的是迭代一个矩阵,这是一个阵列数组。 对于由0到4之间的整数标识的每一行(矩阵的大小为(5,10)),我计算了多少"一个"有。。

我不得不将它分成三个不同的功能,但我想知道是否有更优化的方法来解决这个问题?

let count m i =
    let ret=Array.fold_left (fun x y -> if y=1 then x+1 else x) 0 (m.(i)) in 
    ret;;

let rec clear l =
    match l with 
        |[]->[]
        |(a,b)::[]->if b=0 then [] else (a,b)::[]
        |(a,b)::c->if b=0 then clear c else (a,b)::clear c;;

let all_moves s =
    match s with 
        |(a,_)->clear[(0,count a 0);(1,count a 1);(2,count a 2);(3,count a 3);(4,count a 4)];;

其次,我的主要问题是立即迭代整个矩阵。 我试图计算矩阵中的所有1,除了由param" i"标识的行。 我尝试了几件事,但我现在真的陷入困境。

let countall m i =
    let ret=Array.fold_left (fun x y -> if pos != i then x + y else ()) 
    (Array.fold_left (fun x y -> if y=1 then x+1 else x) 0 (m.(i))) 
    0 m in 
    ret;;

我想提前感谢你的帮助,我想我可能会给你一个矩阵来测试我的功能:

let c = [|[|1; 1; 1; 1; 1; 0; 0; 0; 0; 0|]; [|1; 1; 1; 1; 1; 1; 1; 1; 0; 0|];
[|1; 1; 1; 1; 1; 1; 1; 1; 1; 0|]; [|1; 0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|1; 1; 1; 1; 1; 1; 1; 1; 1; 1|]|]

真诚的,你的, 拉马

2 个答案:

答案 0 :(得分:0)

也许这可以帮到你

let countall m i =
  snd (
    Array.fold_left (fun (lg,c) v ->
      let c=
        if lg = i then c
        else
          Array.fold_left (fun c xy -> if xy=1 then c+1 else c) c v
      in
      (lg+1,c) 
    ) (0,0) m 
  )
;;
  

测试

# countall c 0;;
- : int = 28

答案 1 :(得分:0)

一些指示:

  1. 表单let ret = expr in ret的表达式可以简化为expr。反向应用程序运算符|>通常可用于忽略琐碎的let表达式。
  2. 如果函数以只包含单个子句的匹配表达式开头,则该子句通常可以滚动到函数签名中。例如。 let all_moves s = match s with (a, _) -> ...变为`let all_moves(a,_)= ...'。
  3. ArrayList模块不仅具有折叠功能(以及替代标准库,例如Core,Batteries或ExtLib为它们添加更多功能),可用于简化许多数组/列表处理。
  4. 示例:

    let count_ones row =
      Array.fold_left (fun c x -> if x=1 then c+1 else c) 0 row
    
    let all_moves (mat, _) =
      Array.mapi (fun i row -> (i, count_ones row)) mat
      |> Array.to_list |> List.filter (fun (_, c) -> c != 0)
    

    我不是100%确定countall的预期语义是什么,但如果我正确理解它,则以下内容应该有效(它遵循您尝试的解决方案的基本结构,但依赖于{ {1}}而不是mapi,这是更合适的选择):

    fold_left

    这个功能也可以用不同的方式实现,例如:

    let countall mat k =
      Array.mapi (fun i row -> if i = k then 0 else count_ones row) mat
      |> Array.fold_left (+) 0
    

    在此变体中,我使用本地开放let countall mat k = Array.(append (sub mat 0 k) (sub mat (k+1) (length mat - k - 1))) |> Array.map count_ones |> Array.fold_left (+) 0 ,因此我不必为每个单独的数组操作添加前缀Array.(expr)。此外,在两个版本中Array.都是将plus运算符编写为具有两个参数的函数的方法,并且大致相当于在其位置编写(+)