Dynamic programming example

From HaskellWiki

Dynamic programming refers to translating a problem to be solved into a recurrence formula, and crunching this formula with the help of an array (or any suitable collection) to save useful intermediates and avoid redundant work.

Computationally, dynamic programming boils down to write once, share and read many times. This is exactly what lazy functional programming is for.

1 Sample problems and solutions

1.1 Available in 6-packs, 9-packs, 20-packs

A fast food place sells a finger food in only boxes of 6 pieces, boxes of 9 pieces, or boxes of 20 pieces. You can only buy zero or more such boxes. Therefore it is impossible to buy exactly 5 pieces, or exactly 7 pieces, etc. Can you buy exactly N pieces?

If I can buy i-6 pieces, or i-9 pieces, or i-20 pieces (provided these are not negative numbers), I can then buy i pieces (by adding a box of 6 or 9 or 20). Below, I set up the array

2 Optimization

Simple dynamic programing is usually fast enough (and as always,
profile before optimizing!) However, when you need more speed, it is
usually fairly easy to shave an order of magnitude off the space usage
of dynamic programming problems (with concomitant speedups due to
cache effects.) The trick is to manually schedule the computation in
order to discard temporary results as soon as possible.

Notice that if we compute results in sequential order from 0 to the
needed count, (in the example above) we will always have computed
subproblems before the problems. Also, if we do it in this order we
need not keep any value for longer than twenty values. So we can use
the old fibonacci trick:

At each call of iter, the n parameter contains (total - cur) and the
lst parameter stores buyable for (cur-1, cur-2, cur-3, ...). Also
note that the indexes change meaning through the cons, so we need to
offset the !! indexes by 1.