2015-07-12 53 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等同。