2016-12-05 37 views
1

我現在正在練習矩陣,但我並不確定如何以最有效的方式解決我遇到的一些問題。在矩陣上練習 - 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|]|] 

此致, 拉瑪

回答

0

一些指針:

形式 let ret = expr in ret
  1. 表達式可以簡化爲expr。而反向應用程序運算符|>通常可以用來消除簡單的表達式let
  2. 如果一個函數以只包含一個子句的匹配表達式開始,那麼該子句通常可以放入函數簽名中。例如。 let all_moves s = match s with (a, _) -> ...變成`let all_moves(a,_)= ...'。
  3. ArrayList模塊不僅僅具有摺疊功能(以及替代標準庫,如Core,Batteries或ExtLib可爲其添加更多功能),可用於簡化大量Array/List處理。

例子:

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預期的語義是的,但如果我正確理解它,下面應該工作(它遵循的基本結構你嘗試的解決方案,而是依靠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.前綴的每一個陣列操作。另外,在兩個版本中,(+)都是一種將加號運算符作爲函數寫入兩個參數的方法,大致等同於編寫(fun x y -> x + y)代替它。

+0

事實上mapi在處理矩陣時非常有用,因爲我們可以在索引上應用第一個函數,然後在該行上應用第一個函數。在我的其餘工作中,它確實幫助了我很多。 非常感謝! –

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 
+0

@RamaDesplats如果您需要了解countall解釋,你剛纔問我(個人資料的圖片是非常好的)。 –

+0

如果我對它有所瞭解,那麼我對它的工作原理有一個大概的瞭解。 它需要矩陣的第二個元素,它是第二個數組。 然後它迭代它,如果它不等於我。 它是(lg + 1,c)遍歷矩陣的第一個元素嗎? –

+0

@Rama Desplats,是的,(包括tout)。 –