in reply to puzzle: how many ways to make $100
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:
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) = @_; 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 );
Cheers!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" } );
PS: here are two other cute money denomination puzzles I've posted about, if you're interested: Golf: Buying with exact change & The greedy change-making problem using regexes
blokhead