Search code examples
sml

(sml) I want to count the number of corresponding values in the list


I would like to know the number of cases in which 1 dollar can be expressed in 1,5,10,20,50 cents. For example, the count(100,[50,25]) is: Because 50 * 1 + 25 * 2, it = 3:int is printed. However, in my code, only the front part of the list is printed, so even if I count (100,[50,25]), it = 2:int is printed. In other words, My code is not taking advantage of the whole list. How do I solve this?

SML coin count function:

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;

Solution

  • Consider what happens as you evaluate your test expression of count (100, [50, 25]).

    cnt is 0, y is 50, and ys is [25].

    y times 2 does equal 100, so it returns cnt+2 which is 2. Nothing further happens.

    When it comes to recursion, remember than the parameter list to a function is your means of communication. It seems like cnt is something that should be passed as a parameter so you can update it between recursive calls.

    With count(x, []) = 0 you already have an exit point that will stop the recursion.

    Edit: Based on comments, it looks like you're trying to figure out how many times each value in a list goes into a value x.

    So the end result of your recursive function isn't a single integer. It's a list of integers. Or better yet, of tuples containing the value to look for, and the number of times it goes into x.

    So if the list is empty, the result is obvious.

    fun count(x, []) = []
    

    It's an empty list. Otherwise, we need to append something onto a list.

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

    Of course, we also have functions like map that basically do this for us.

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