#1
  1. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2001
    Posts
    19
    Rep Power
    0

    Multiple Permutation handling


    I'm trying to figure out some code that will loop thru pre-defined lists and output all combinations (concatenations). Specifically of shirts and size/color/etc options.

    For example, here are some lists:



    My code needs to output something like this:

    SKU1TSBLU
    SKU1TSGRN
    SKU1TSWHT
    SKU1TSBLK
    SKU1TMBLU
    SKU1TMGRN
    SKU1TMWHT
    SKU1TMBLK
    ...
    SKU5H2XWHT
    SKU5H2XBLK

    So basically every combination of every option for each sku.

    I have been doing some looping and can get there in a very ugly, inefficient manner, but I just know there's an easier way.

    Any help appreciated.
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Location
    Paris area, France
    Posts
    843
    Rep Power
    496
    Can you tell us why is your manner ugly and inefficient? Please show us the code.

    If you really need all the combinations, then you really have to bite the bullet and generate all of them, one way or another

    You can do that yourself, with for example four nested foreach loops, which is not necessarily that ugly and inefficient. For example, the following is rather clean, straight forward and easy to understand:

    Perl Code:
    foreach my $s1 (@set1) {
         foreach my $s2 (@set2) {
              foreach my $s3 (@sizes) {
                   foreach my $s4 (@colors) {
                        print "$s1$s2$s3$s4\n";
                   }
             }
         }
    }


    You could probably "hide" some of the work by a clever multiple use of the map function, or by using some form of recursive descent through the arrays (for example, a recursive call to an iterator function going through the arrays and expanding the return list on each call), but I am not sure the code would be much shorter or easier to read, and it would also probably not be really more efficient.

    Then, you have the easy way: you can also hide almost all the work by using a CPAN module such as Algorithm::Combinatorics.
  4. #3
  5. No Profile Picture
    Registered User
    Devshed Newbie (0 - 499 posts)

    Join Date
    May 2001
    Posts
    19
    Rep Power
    0
    That's actually perfect. Thanks so much.
  6. #4
  7. No Profile Picture
    Contributing User
    Devshed Novice (500 - 999 posts)

    Join Date
    Jun 2012
    Location
    Paris area, France
    Posts
    843
    Rep Power
    496
    Hi Midget,

    I just copy here below part of my post in answer to your cross post of your question on Perl Monks forum.

    As I said, I think the four nested foreach loops I suggested above is probably the best solution: clean, straight forward, easy to understand and efficient.

    For the fun of it, however, let me suggest a kind of "Schwartzian" solution, which could also be called a "Lisp written in Perl" solution (or Scheme, or Haskell, or whatever functional language written in Perl):

    Perl Code:
    my @sku = qw/SKU1 SKU2 SKU3/;
    my @tslh = qw/t s l h/;
    my @colors = qw/BLU GRN WHT BLK /;
    my @sizes = qw / S M L XL 2X /;
     
    print map { $col = $_; map { $siz = $_; map {$a1 =$_; map "$_ $a1 $siz $col\n", @sku;} @tslh} @sizes } @colors;


    (I have added spaces between the fields to make the output easier to read.) This prints (I copy only the beginning and the end of the 240-line printout):

    Code:
    SKU1 t S BLU
    SKU2 t S BLU
    SKU3 t S BLU
    SKU1 s S BLU
    SKU2 s S BLU
    SKU3 s S BLU
    SKU1 l S BLU
    SKU2 l S BLU
    (...)
    SKU2 s 2X BLK
    SKU3 s 2X BLK
    SKU1 l 2X BLK
    SKU2 l 2X BLK
    SKU3 l 2X BLK
    SKU1 h 2X BLK
    SKU2 h 2X BLK
    SKU3 h 2X BLK
    The beauty (and fun) of this solution is of course that it holds in just one line of code (in pure Perl, without using a module to do the work behind the scene).

    There are a number of downsides to this solution, however: first, it is far less easy to understand, it is actually hardly readable. Even though I just wrote it, I am not sure how I would explain it to make it clearly understandable.

    To tell the truth, it was also a bit complicated for me to write it: it took me about 3 minutes to write the foreach nested loops above (which I did not even need to test), and and it took me slightly more than half an hour to get the nested map function calls to work correctly. So, in brief, this was just for the fun, I do not recommend this solution.
    Last edited by Laurent_R; March 3rd, 2013 at 06:16 PM.

IMN logo majestic logo threadwatch logo seochat tools logo