2016-11-11 71 views
0

我正在嘗試在Ocaml中執行Array的所有組合。 我想做一個遞歸函數,recives一個數組,它的初始狀態需要爲let a = [|0;0;0|],我需要像第一次迭代那樣遞歸地改變它,需要是a = [|1;0;0|]和下一個a = [|0;1;0|]等等,直到它達到a = [|1;1;1|]所有可能的組合,所以在這種情況下需要做2^3個變化。 我知道我不是很明確,但我有點難以解釋,但如果有人能幫助我,我會感激。Ocaml中的數組操作

+0

你能後至今你已經嘗試了什麼? –

回答

-1
let combinaison f n = 
    let rec aux acc n = 
    if n=0 then List.iter f acc 
    else (
     aux (List.map (fun l -> 0::l ) acc) (n-1); 
     aux (List.map (fun l -> 1::l ) acc) (n-1); 
    ) 
    in 
    aux [[]] n 
;; 

測試

combinaison (fun lx -> 
    let a=Array.of_list lx in 
    Array.iter (fun x -> 
    Printf.printf "%d " x 
) a ; 
    Printf.printf "\n" 
) 3;; 

0 0 0 
1 0 0 
0 1 0 
1 1 0 
0 0 1 
1 0 1 
0 1 1 
1 1 1 
+0

感謝的人,其實我一直在笑 – Funnymemes

+0

好吧@Funnymemes有一個美好的一天。 –

2

數組是一個可變數據結構,所以如果您要在每次遞歸調用中對它進行變異,那麼就會發生突變。基本上,這意味着,在調用2^3之後,數組的狀態將是最後一個組合。所以,這樣做根本沒有意義。一個有效的解決方案是創建一個函數,該函數將採用初始數組,並返回所有組合的列表。更有效的解決方案是編寫一個函數,該函數將採用另一個函數,並將其應用於所有組合(或摺疊所有組合)。這將允許您節省內存,因爲您不需要存儲所有組合。

大綱將實現以下接口:

type state 
val zero : state 
val next : state -> state option 
val value : state -> int array 

如果狀態將是一個光標,將通過組合的空間移動。它可以是一個整數或整數數組,或其他任何東西。一旦這些功能被實現可以方便地實現的功能如下:

let fold_combinations f init = 
    let rec fold state x = 
    let x = f (value state) x in 
    match next state with 
    | None -> x 
    | Some state -> fold state x in 
    fold zero init 

最後,您的示例示出了不是所有可能的組合或排列,但比特寬度的所有可能的二進制值等於輸入數組的長度。如果這真的是你想要解決的任務,那麼你可以將整數轉換爲二進制表示。在那種情況下,state的好選擇是int,然後next函數是一個增量,它將在2^k-1處停止,其中k是初始狀態的長度。並且value函數將只將一個整數轉換爲位數組,其中n位(元素)可以被確定爲state land (1 lsl n)。您可以使用Array.init每次創建一個全新的數組,或者,您可以遍歷現有的數組。這樣會更有效率,但容易出錯。