use strict; use warnings; my $n = 0; my $total = 0; my $num_left = 0; my @order; sub factorial { my $input = CORE::int(shift); return "Error - unable to take factorial of an negative number ($input)" if $input < 0; return "Error - factorial result is greater than system limit ($input)" if $input > 170; return 1 if $input == 0; my $result = 1; for (my $i=2; $i<=$input; $i++) { $result *= $i } return $result; } sub init { my ($size) = @_; @order = (0..$size-1); $n = $size; $total = $num_left = &factorial($size); } sub get_next { if ($num_left == $total) { $num_left--; return @order; } # Find largest index j with a[j] < a[j+1] my $j = scalar(@order) - 2; while ($order[$j] > $order[$j+1]) { $j--; } # Find index k such that a[k] is smallest integer # greater than a[j] to the right of a[j] my $k = scalar(@order) - 1; while ($order[$j] > $order[$k]) { $k--; } # Interchange a[j] and a[k] @order[($k,$j)] = @order[($j,$k)]; # Put tail end of permutation after jth position in increasing order my $r = scalar(@order) - 1; my $s = $j + 1; while ($r > $s) { @order[($s,$r)]=@order[($r,$s)]; $r--; $s++; } $num_left--; return(@order); } &init(9); while($num_left) { print(join(':',&get_next()).$/); }