in reply to pathsearch/backtracking in Perl - how to solve a problem apparently requiring it? (comparison of Perl with Standard ML)

Ok, I looked at the description in the ML page you provided -- It's about 3/4 of the way down the page. I'll reproduce it here:
What is at issue is that the obvious "greedy" algorithm for making change that proceeds by doling out as many coins as possible in decreasing order of value does not always work. Given only a 5 cent and a 2 cent coin, we cannot make 16 cents in change by first taking three 5's and then proceeding to dole out 2's. In fact we must use two 5's and three 2's to make 16 cents. Here's a method that works for any set of coins:
exception Change fun change _ 0 = nil | change nil _ = raise Change | change (coin::coins) amt = if coin > amt then change coins amt else (coin :: change (coin::coins) (amt-coin)) handle Change => change coins amt
The idea is to proceed greedily, but if we get "stuck", we undo the most recent greedy decision and proceed again from there. Simulate evaluation of the example of change [5,2] 16 to see how the code works.
With that in mind, I have written something in Perl that parallels his solution as closely as I could:
use strict; use warnings; my $amount = 16; my $coinset = [5,2]; { my $Exception = 0; sub change { my ($cset, $amt) = @_; if ($amt == 0) { return [] } if (@$cset == 0) { $Exception = 1; return [] } my $coin = shift @$cset; if ($coin > $amt) { print "$coin > $amt\n"; return [change($cset, $amt)]; } else { print "Checking $amt - $coin\n"; my $rval = [$coin, @{change( [$coin, @$cset], $amt - $coin )}]; if ($Exception) { print "Exception forces backing up to $amt\n"; $Exception = 0; $rval = [@{change($cset, $amt)}]; } return $rval; } } } use Data::Dumper; print Dumper(change($coinset, $amount)), "\n";

Caution: Contents may have been coded under pressure.
  • Comment on Re: pathsearch/backtracking in Perl - how to solve a problem apparently requiring it? (comparison of Perl with Standard ML)
  • Select or Download Code

Replies are listed 'Best First'.
Re^2: pathsearch/backtracking in Perl - how to solve a problem apparently requiring it? (comparison of Perl with Standard ML)
by Anonymous Monk on Nov 12, 2004 at 23:10 UTC
    I don't like global vars (even in disguise). So thats my take on yours.
    #!/usr/bin/perl use strict; use warnings; my $amount = 16; my $coinset = [5,2]; sub change { my ($cset, $amt) = @_; if ($amt == 0) { return [] } if (@$cset == 0) { return "" } my $coin = shift @$cset; if ($coin > $amt) { print "$coin > $amt\n"; $coin=change($cset, $amt); return$coin if!ref$coin; return[$coin]; } else { print "Checking $amt - $coin\n"; my $rval =change( [$coin, @$cset], $amt - $coin ); return[$coin, @{$rval}]if ref $rval; print "Exception forces backing up to $amt\n"; return [@{change($cset, $amt)}]; } } use Data::Dumper; print Dumper(change($coinset, $amount)), "\n";
      It's not a global, it's a static. What's not to like about it?

      Caution: Contents may have been coded under pressure.