This is just a fun little exercise I had to do for a homework once (in Java rather than Clojure though). Basically, the goal is to find the number of different coin stacks you can build with the coins 1,2,5 and 10 to form a number N (I believe a closed form solution for this exists, but this isn't what this is about).
My solution here works, but I'm not quite happy with it:
- Explicit loop. Not sure how to do away with it though.
- A few functions there that I think should be core functions, but I can't find them.
- Even if they aren't in core, my functions could probably be written somewhat more concisely
Anyways, here's my code (by the way, the function is called "fast-iterative" because the exercise was about calculating these values recursively. Which I think is insane due to the branching factor, but whatever):
(ns test.coin-stacks)
(def maximum (partial reduce max))
(defn shift-vector
"Shifts v one to the left, insert shift-val at the right"
[v shift-val]
(conj (vec (rest v)) shift-val))
(defn update
"Updates ks in m with f applied to ks.
I can't believe I have to write this myself."
[m ks f]
(apply assoc m (interleave ks (map (comp f m) ks))))
(defn fast-iterative-coinstacks
"Returns the number of ways to form a coin stack with a total
value of n with coins"
[n coins]
(let [max-coin (maximum coins)
initial-stacks (apply conj [1] (repeat max-coin 0))]
(loop [stacks initial-stacks iteration 0]
(if-not (< iteration n)
(first stacks)
(recur (shift-vector (update stacks coins (partial +' (stacks 0))) 0)
(inc iteration))))))