I’m looking at Problem thirty one on Project Euler, which asks, how many different ways are there of making £2 using any number of coins of 1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p).
There are recursive solutions, such as this one in Scala (credit to Pavel Fatin)
def f(ms: List[Int], n: Int): Int = ms match {
case h :: t =>
if (h > n) 0 else if (n == h) 1 else f(ms, n - h) + f(t, n)
case _ => 0
}
val r = f(List(1, 2, 5, 10, 20, 50, 100, 200), 200)
and although it runs fast enough, it’s relatively inefficient, calling the f function around 5.6 million times.
I saw someone else’s solution in Java which was programmed dynamically (credit to wizeman from Portugal)
final static int TOTAL = 200;
public static void main(String[] args) {
int[] coins = {1, 2, 5, 10, 20, 50, 100, 200};
int[] ways = new int[TOTAL + 1];
ways[0] = 1;
for (int coin : coins) {
for (int j = coin; j <= TOTAL; j++) {
ways[j] += ways[j - coin];
}
}
System.out.println("Result: " + ways[TOTAL]);
}
This is much more efficient and passes the inner loop only 1220 times.
While I could obviously translate this more or less verbatim into Scala using Array objects, is there an idiomatic functional way to do this using immutable data structures, preferably with similar conciseness and performance?
I have tried and become stuck trying to recursively update a List before deciding I’m probably just approaching it the wrong way.
Whenever some part of a list of data is computed based on a previous element, I think of
Streamrecursion. Unfortunately, such recursion cannot happen inside method definitions or functions, so I had to turn a function into a class to make it work.The definitions of
lowerandhigherare not necessary — I could easily replace them withstream take coinandstream drop coin, but I think it’s a little clearer (and more efficient) this way.