in reply to puzzle: how many ways to make $100
There are about as many approaches to this problem as there are ways to make change for $100 ;) ... There are a few more examples/ideas in this thread: How to generate restricted partitions of an integer (the solutions towards the bottom are the ones that actually work!)
And for yet another opinion on the subject (s/coin/bill/ throughout the rest of this, if you prefer)... Just because it's a little simpler, I would first just try counting the ways to make change for the amount (i.e, without keeping track of what those ways are). To make change for an amount, I first choose which coin will be the biggest coin that I'm going to include, which can be any available coin. I subtract that coin from my total, and then I need to find how many ways I can make change for what's left over, using none of the coins bigger than the one I just chose (since it was supposed to be the biggest). Of course, that's just nothing more than a recursive subcall! In code it looks like this:
sub make_change {
my ($N, @coins) = @_;
return 0 if $N < 0;
return 1 if $N == 0;
my $total = 0;
for (0 .. $#coins) {
$total += make_change( $N$coins[$_], @coins[$_ .. $#coins] );
}
return $total;
}
print make_change( 100 => 50, 25, 10, 5, 1 );
Then instead of just counting, I'd modify the code to keep track of the choices it made so far (using an additional argument), and when it gets to the end, do something with them. This is called using an accumulator (I called it @so_far for this sub).
sub make_change {
my ($N, $coins, $callback, @so_far) = @_;
my @coins = @$coins;
return if $N < 0;
return $callback>(@so_far) if $N == 0;
for (0 .. $#coins) {
make_change( $N  $coins[$_],
[@coins[ $_ .. $#coins ]],
$callback,
($coins[$_], @so_far) );
}
}
make_change(
100,
[50, 25, 10, 5, 1],
sub { print "@_\n" }
);
Cheers!
PS: here are two other cute money denomination puzzles I've posted about, if you're interested: Golf: Buying with exact change & The greedy changemaking problem using regexes
