(sml) 我要统计列表中对应值的个数

问题描述

我想知道1美元可以用1、5、10、20、50美分表示的情况。 例如,count(100,[50,25]) 是: 因为 50 * 1 + 25 * 2,it = 3:int is printed. 但是,在我的代码中,只打印了列表的前部,所以即使我 count (100,25]),it = 2:int is printed. 换句话说,我的代码没有利用整个列表。 我该如何解决这个问题?

SML 硬币计数功能

fun count(x,[]) = 0
| count (x,y::ys) =
let val cnt = 0
in if y*2 = x then cnt+2
else if y*4 = x then cnt + 4
else if y*10 = x then cnt + 10
else if y*10 = x then cnt + 10
else if y*20 = x then cnt + 20
else count(x-y,ys)
end;

解决方法

考虑评估 count (100,[50,25]) 的测试表达式时会发生什么。

cnt0y50,而 ys[25]

y 乘以 2 does 等于 100,因此它返回 cnt+2,即 2。没有进一步的事情发生。

说到递归,请记住,函数的参数列表是您的通信方式。似乎 cnt 应该作为参数传递,以便您可以在递归调用之间更新它。

使用 count(x,[]) = 0,您已经有了一个可以停止递归的退出点。

编辑:根据评论,您似乎正在尝试计算列表中每个值进入值 x 的次数。

所以你的递归函数的最终结果不是一个整数。这是一个整数列表。或者更好的是,包含要查找的值的元组,以及它进入 x 的次数。

所以如果列表为空,结果很明显。

fun count(x,[]) = []

这是一个空列表。否则,我们需要将某些内容附加到列表中。

fun count(x,[]) = []
  | count(x,y::ys) = 
      (y,x div y) :: count(x,ys)

当然,我们也有像 map 这样的函数,基本上可以为我们做这些。

fun count(x,lst) = List.map (fn y => (y,x div y)) lst