Reputation: 1691
Apologies if this looks like another problem - there are quite a lot of solutions and I didn't find what I'm looking for, but I may well have missed it. Also apologies if title isn't best description - not sure how else to word it.
I have five 'features' as strings, e.g.:
$height $width $depth $length $colour
I want to get all the different unique combinations starting with 5 and going down to 1 e.g.:
5: $height $width $depth $length $colour
4: $height $width $depth $length
4: $height $width $depth $colour
4: $height $width $length $colour
4: $height $depth $length $colour
4: $width $depth $length $colour
...
and so on
...
1: $height
1: $width
1: $depth
1: $length
1: $colour
I don't know if it makes a difference, but in code I plan to use &&
and !$string
, e.g.:
4: $height && $width && $depth && $length && !$colour
4: $height && $width && $depth && !$length && $colour
4: $height && $width && !$depth && $length && $colour
4: $height && !$width && $depth && $length && $colour
4: !$height && $width && $depth && $length && $colour
and so on.
I was fine doing this by hand when I had 4 features, but with 5 it's too much! I thought putting the variables in a hash would may be good starting point, but as for the actual algorithm... Any help appreciated!
Edit: just realised it may not be clear, but I want to be able to 'query' each combination as they will be in if/elsif statements, so if (h && w && !d ...)
Upvotes: 1
Views: 540
Reputation: 58534
You want unique combinations? Try Math::Combinatorics.
use strict;
use warnings;
use feature qw(say);
use Math::Combinatorics qw(combine);
our @primary_qualities = qw(height width depth length colour);
for my $n (1 .. @primary_qualities) {
say "@$_" for combine($n, @primary_qualities);
}
You'll have to handle the degenerate case (no height, no width, no depth, no length, no colour) yourself.
Upvotes: 1
Reputation: 67900
Have a look at Algorithm::Permute
use Algorithm::Permute;
my @array = ($height, $width, $depth, $length, $colour);
Algorithm::Permute::permute { print "@array" } @array;
This is also described in perlfaq: How do I permute N elements of a list?
Upvotes: 3
Reputation: 118595
Encode a configuration as a 5 bit integer and just iterate from 0 to 25-1.
for ($i = 0; $i < 1<<5; $i++) {
my @output;
push @output, $i & 1 ? '$height' : '!$height';
push @output, $i & 2 ? '$width' : '!$width';
push @output, $i & 4 ? '$depth' : '!$depth';
push @output, $i & 8 ? '$length' : '!$length';
push @output, $i & 16 ? '$colour' : '!$colour';
print join(' && ', @output), "\n";
}
Upvotes: 6
Reputation: 26861
Try with Algorithm::Permute
use Algorithm::Permute;
my $props = [$height, $width, $depth, $length, $colour];
foreach my $n ( 1.. scalar( @$props) ){
my $p = new Algorithm::Permute($props, $n);
#you can create r of n objects permutation generator, where r <= n
while (@res = $p->next) {
print join(", ", @res), "\n";
}
}
Upvotes: 0