2014-02-13 86 views
1

目前我試圖讓列表的使用功能來創建:OCaml中和創建列表

0 V12 V13 V14 
V21 0 V23 V24 
V31 V32 0 V34 
V41 V42 V43 0 

的方式,我發現這樣做是使用論文公式:

(2*V1 - 1)*(2*V2-1) = for spot V(1,2) in the Matrix 
(2*V1 - 1)*(2*V3-1) = for spot V(1,3) in the Matrix 
etc 

因此到目前爲止,我有:

let singleState state = 
if state = 0.0 then 0.0 
else 
    ((2.0 *. state) -. 1.0);; 


let rec matrixState v = 
match v with 
| [] -> [] 
| hd :: [] -> v 
| hd :: (nx :: _ as tl) -> 
    singleState hd *. singleState nx :: matrixState tl;; 

我的結果出來是:

float list = [-3.; -3.; -3.; -1.] 

當他們應該列出看起來名單如下:

0 -1 1 -1 
-1 0 -1 1 
1 -1 0 -1 
-1 1 -1 0 

所以,相反,它使列表是製作只有一個名單列表。我也有麻煩搞清楚如何使對角線0

的簽名應該是這樣的:

val singleState : float list -> float list list = <fun> 
val matrixState : float list list -> float list list = <fun> 

和我得到

val singleState : float -> float = <fun> 
val matrixState : float list -> float list = <fun> 

任何想法?

+0

您所使用的語言爲w ritten「OCaml」,大寫字母O和大寫字母C. http://caml.inria.fr/ocaml/index.en.html –

回答

0

隨着一些修正,你的功能會使結果的一行。然後你可以爲你需要的每一行調用一次。重複呼叫的好方法可能是List.map

假設這主要是一個學習鍛鍊,這可能是件好事先製作一個矩陣是這樣的:

V11 V12 V13 V14 
V21 V22 V23 V24 
V31 V32 V33 V34 
V41 V42 V43 V44 

我認爲這將是一個更容易計算。

然後你可以用零代替對角線。這裏有一些代碼可以代替對角線:

let replnth r n l = 
    List.mapi (fun i x -> if i = n then r else x) l 

let zerorow row (n, res) = 
    (n - 1, replnth 0.0 n row :: res) 

let zerodiag m = 
    let (_, res) = List.fold_right zerorow m (List.length m - 1, []) in 
    res 
+0

啊是的,這是一個練習,但它說不使用列表。函數會使其變得相當困難 – user081608

+0

如果這是一個練習,我不想爲你編寫它:-)你可以使用顯式遞歸來打開這些函數。或者你可以編寫自己的列表功能版本。 –

0

我寧願用數組來處理工作。

一個不錯的功能,採用的是那麼Array.init,它的工作原理是這樣,

# Array.init 5 (fun x -> x);; 
- : int array = [|0; 1; 2; 3; 4|] 

我們注意到,發揮我們的數組的大小的作用。

但是當你想要一個矩陣,我們需要建立數組,它是一個有兩個呼叫Array.init,最後一個嵌套到第一個實現的Array,

# Array.init 3 (fun row -> Array.init 3 (fun col -> row+col));; 
- : int array array = [|[|0; 1; 2|]; [|1; 2; 3|]; [|2; 3; 4|]|] 

注意,我已經打電話給我變量col表示它們對應於我們矩陣的行索引和列索引的事實。

最後,爲您的公式使用的參考矢量V容值[| V1,V2,V3,V4 |],我們需要創建一個包含調用到我們矩陣建設者, (對數組tab的小區n的值保持就像訪問,從而tab.(n-1)

並最終導致我們對工作示例,

let vect = [|1;2;3;4|] 

let built_matrix = 
    Array.init 4 (fun row -> 
    Array.init 4 (fun col -> 
     if col=row then 0 
     else vect.(row)+vect.(col))) 

當然,你必須適應它爲y我們的便利,以便根據您的要求匹配這段代碼。

關於語法的注意事項,
每次重複陣列都可以避免使用OCaml的一些很好的功能。
我們可以在本地打開,像這樣一個模塊,

let built_matrix = 
let open Array in 
    init 4 (fun row -> 
    init 4 (fun col -> 
     if col=row then 0 
     else vect.(row)+vect.(col))) 

更短,let open Array in ...可以寫爲Array.(...),下面的優秀UTOP下解釋的代碼塊,說明它(我打算從中獲利這個機會,將我們的矩陣的轉換列表的列表)。

utop # 
Array.(
    to_list 
    @@ map to_list 
    @@ init 4 (fun r -> 
    init 4 (fun c -> 
     if r = c then 0 
     else vect.(r)+ vect.(c)))) 
;; 
- : int list list = [[0; 3; 4; 5]; [3; 0; 5; 6]; [4; 5; 0; 7]; [5; 6; 7; 0]] 

我希望它能幫助