Apocalypse has asked for the wisdom of the Perl Monks concerning the following question:

Hello, fellow Monks! I am not a mathematician, so I am sure there's a word for this out there. I want to generate every possible combination of words taken from an array. The array will have words, I want it to be like this: @array = qw( hey foo bar ); Output:
hey
foo
bar
hey foo
hey bar
hey hey
hey foo bar
hey foo hey
hey foo foo
And so on... I would love the ability to control the number of repetitions allowed in the output, and haven't been able to find any module to do so. Data::Random does a nice job of randomly selecting random numbers of elements, but I want a linear way of generating them - It is for a test suite for a program I'm writing right now. Any help would be greatly appreciated!

Replies are listed 'Best First'.
Re: Generating sequence of words
by PodMaster (Abbot) on Aug 13, 2003 at 08:04 UTC
      Those are a helpful start for a search, but he did say combinations, not permutations. The string "foo foo foo" is a valid combination but would not be a valid permutation of qw(hey foo bar).

      --
      [ e d @ h a l l e y . c c ]

Re: Generating sequence of words
by cchampion (Curate) on Aug 13, 2003 at 10:11 UTC
      ++ cchampion!
      Thanks for the helpful nodes, and everyone, now that I know the word is "permutation", I can super search for it and come up with more nodes. Thanks again!
        After some research, I have decided that the word "permutation" is not what I wanted, and halley's comment about my looking for "combinations" is correct.
        This node: http://www.perlmonks.org/index.pl?node_id=128286
        Does everything I want, thanks again tye!
Re: Generating sequence of words
by sgifford (Prior) on Aug 13, 2003 at 07:11 UTC
    Here's one way:
    #!/usr/bin/perl -w use strict; use vars qw(@array); @array = qw( hey foo bar ); combinations(scalar(@array), [], \@array); sub combinations { my($count,$sofar,$remaining)=@_; if (!$count) { print join(" ",@$sofar),"\n"; return; } combinations($count-1,[@$sofar],[@$remaining]); foreach my $r (@$remaining) { combinations($count-1,[@$sofar, $r], [@$remaining]); } }

    It's a recursive technique that selects all possibilities for each position in the output array, including leaving it empty. Each call to combinations iterates through all possible values for the current position, then calls itself to determine what can go in the subsequent positions.

    A possible bug is that it outputs all of ('foo','',''), ('','foo',''), and ('','','foo'), even though all are the single word 'foo'. If that's a problem, you can store the combinations into an array then filter out duplicates.