2015-07-12 54 views
5

我正在自學OCaml,而我用於練習的主要資源是Cornell從他們的3110課程中提供的一些問題集。其中一個問題是編寫一個反轉int的函數(即:1234→4321,-1234→-4321,2→2→-10→-1等)。顛倒OCaml中的int

我有一個有效的解決方案,但我擔心,這不完全是地道的OCaml:

let rev_int (i : int) : int = 
    let rec power cnt value = 
    if value/10 = 0 then cnt 
    else power (10 * cnt) (value/10) in 
    let rec aux pow temp value = 
    if value <> 0 then aux (pow/10) (temp + (value mod 10 * pow)) (value/10) 
    else temp in 
    aux (power 1 i) 0 i 

它可以正常工作在所有情況下,據我所知道的,但它只是似乎嚴重「 un-OCaml「給我,特別是因爲我用兩個內部函數遍歷整個int長度。所以我只是想知道是否有更多的「OCaml」方式來做到這一點。

+0

爲什麼不是int - > string - > char數組 - >顛倒的char數組 - > string - >顛倒的int?這不是OCaml,但是我在SML/NJ中做了類似的事情(使用內爆和爆炸哪些OCaml似乎缺少),同時玩弄https://en.wikipedia.org/wiki/Lychrel_number。在函數式編程中將簡單的轉換鏈接在一起是相當習慣的。這可能需要對數據進行多次傳遞,但「避免過早優化」在學習語言時是很好的建議。 –

+4

我沒有看到任何關於您的解決方案的單一性。可能有一些更聰明的解決方案,但這是一個不同的問題。 –

回答

4

我會說,以下是足夠地道的。

(* [rev x] returns such value [y] that its decimal representation 
    is a reverse of decimal representation of [x], e.g., 
    [rev 12345 = 54321] *) 
let rev n = 
    let rec loop acc n = 
    if n = 0 then acc 
    else loop (acc * 10 + n mod 10) (n/10) in 
    loop 0 n 

但正如傑弗裏在評論說,您的解決方案是很地道的,雖然不是最好的一個。

順便說一句,我自己的風格,將是這樣寫:

let rev n = 
    let rec loop acc = function 
    | 0 -> acc 
    | n -> loop (acc * 10 + n mod 10) (n/10) in 
    loop 0 n 

正如我寧願模式匹配if/then/else。但這是我個人品味的問題。

+0

謝謝;這是我所設想的。關於其他答案,我可能應該在我的帖子中提到,我試圖避免使用像string_of_int這樣的「內置」函數。 –

1

我可以建議你做的一些方法:

let decompose_int i = 
    let r = i/10 in 
    i - (r * 10) , r 

此功能允許我分解整數,如果我有一個列表。 例如1234分解爲4123。 然後我們將其反轉。

let rec rev_int i = match decompose_int i with 
    | x , 0 -> 10 , x 
    | h , t -> 
    let (m,r) = rev_int t in 
    (10 * m, h * m + r) 

這裏的想法是返回101001000 ...等等就知道在哪裏放置最後一位。


我想在這裏做的是把他們當作我會像對待名單,decompose_int是一個List.hdList.tl等同。