Listing 1.
perm.pl
Jason Brazile
Iterating over Permutations
The Perl Journal, Fall 1998
 
#!/usr/bin/perl
use strict;

sub permute_init {
    my ($digits) = shift;
    return([ [[], $digits] ]);
}

sub permute_next {
    my ($state) = shift;
    my ($left, $right);
    my ($newleft, $newright);
    my ($val, $item, $i, $done);
        
    $item = pop(@$state);
        
    if (defined($item)) {
        
         ($left, $right) = @$item;
                 
         while (! $done) {
                 
            if (scalar(@$right) > 0) {
                        
                foreach $i (0 .. (scalar(@$right) - 1)) {
                    $newright = [];
                    $newleft = [];
                    @$newright = @$right;
                    @$newleft = @$left;
                    push(@$newleft,
                         splice(@$newright, $i, 1));
                    unshift(@$state,
                         [$newleft, $newright]);
                                                 
                }
             }
             if (scalar(@$left) > 0) {
                 $val = join('', @$left);
                 $done = 1;
             } else {
                 $item = pop(@$state);
                 ($left, $right) = @$item;
             }
          }
      }
      return($state, $val);
          
}

sub main {
    my ($state1, $state2, $val1, $val2);
    my ($digits, $result, $count, $tries);
    my ($tmp, $diff, $len, $bests, $bestdiff);
        
    $digits = [9, 2, 3, 8, 6];
    $result = 5029;

    $| = 1;
    $tries = 0; $bestdiff = 99999;
    $len = scalar(@$digits);
        
    $state1 = &permute_init($digits);
        
    ($state1, $val1) = &permute_next($state1);
    while (defined($val1)) {
        
        $state2 = &permute_init($digits);
                
        ($state2, $val2) = &permute_next($state2);
        while (defined($val2)){
                
            $tmp = $val1 - $val2 - $result;
            $tmp = -$tmp if $tmp < 0;
                        
            if ($tmp == $bestdiff){
                $count++;
                push(@$bests, [$val1, $val2]);
            } elsif ($tmp < $bestdiff){
                $count = 1; 
                                
                $bests = [[$val1, $val2]];
                $bestdiff = $tmp;
                                
            }
                        
            $tries++;
            ($state2, $val2) = &permute_next($state2);
         }
         ($state1, $val1) = &permute_next($state1);
                 
    }
        
print("$tries different possibilities were tested.\n");
print("There are $count answers that are off by $bestdiff\n");

    foreach $tmp (@$bests) {
        ($val1, $val2) = @$tmp;
         printf "%${len}d - %${len}d = %${len}d\n",
                 $val1, $val2, $val1 - $val2;
    }
}

&main