dgBP
dgBP

Reputation: 1691

Practical Perl solution to permutate through list for unique combinations

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

Answers (4)

pilcrow
pilcrow

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

TLP
TLP

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

mob
mob

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

Tudor Constantin
Tudor Constantin

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

Related Questions