假设我们使用一个列表来反向表示数字,每个节点都是数字内的一个数字。
所以[1;2;3;4;5]
是数字54321
现在我们想要加上两个这样的列表,例如,添加[1; 2]和[3; 4],我们得到[4; 6],这是数字64.
这是我的代码:
let add l1 l2 =
let rec add_to up acc = function
| [] -> if up = 1 then 1::acc else acc
| hd::tl ->
let s = hd+up in
if s >= 10 then add_to 1 ((s-10)::acc) tl
else List.rev_append tl (s::acc)
and
add_up up acc = function
| [], [] -> if up = 1 then 1::acc else acc
| l, [] | [], l -> (add_to up [] l) @ acc
| hd1::tl1, hd2::tl2 ->
let s = hd1+hd2+up in
if s >= 10 then add_up 1 ((s-10)::acc) (tl1, tl2)
else add_up 0 (s::acc) (tl1, tl2)
in
List.rev (add_up 0 [] (l1, l2))
这个想法非常简单,只需从两个列表中添加两个hds,如果两个hds的总和大于或等于10,则将1传递给下一个。
但是,我觉得我的代码看起来并不漂亮。
@
。任何人都可以帮助我让它变得更美丽吗?
答案 0 :(得分:1)
我认为诀窍是概括。其实质是增加三件事,而不是两件事。
let sum a b =
let rec isum a b c =
match a, b with
| [], [] -> if c = 0 then [] else [c]
| [], x | x, [] -> isum [0] x c
| ah :: at, bh :: bt ->
let s = ah + bh + c in
(s mod 10) :: isum at bt (s / 10)
in
isum a b 0
此代码不是尾递归。尾递归版本不那么优雅。
注意:我假设您使用[]
来表示0。