One solution that comes to mind is to generate the
list out-of-order then sort it into order.
@bar=sort {zc($a) <=> zc($b)}
permute([0..2],[0..2],[0..2],[0..2],[0..2]);
sub zc{
my $arg=shift;
my @a=split //,$arg;
return (grep /0/,@a[0..1])+(grep /0/,@a[3..4]);
}
This is shorter (lines-of-code wise) than the 16 loops you describe, but will
run slower. You could build the same sort of idea
into the algorithm by using a heap w/ the same sort rule,
but the end result would be algorithmically equivalent
performance wise.
Another approach (it is too late tonight for me
to work this out completely):
Assume that permute($a,$b,$c,$d,$e) takes array references
as its arguments and returns a list of all the permutations of the elements
of those lists.
Also assume that the function nz takes a list reference and
returns all non-zero elements of that list.
Then what you want to do is call permute like this:
push @list,permute(nz($a),nz($b),$c,nz($d),nz($e));
push @list,permute([0],nz($b),$c,nz($d),nz($e));
push @list,permute(nz($a),[0],$c,nz($d),nz($e));
push @list,permute(nz($a),nz($b),$c,[0],nz($e));
push @list,permute(nz($a),nz($b),$c,nz($d),[0]);
push @list,permute([0],[0],$c,nz($d),nz($e));
etc...
Basically the "16 loops" you describe above. There is a
very definite pattern to how the arguments of permute
are set up for each call.
Now all that is left is to figure out how
to generate that pattern.