File Coverage

blib/lib/Math/Cartesian/Product.pm
Criterion Covered Total %
statement 44 44 100.0
branch 12 14 85.7
condition n/a
subroutine 6 6 100.0
pod 0 1 0.0
total 62 65 95.3


line stmt bran cond sub pod time code
1             =head1 Name
2              
3             Math::Cartesian::Product - Generate the cartesian product of zero or more lists.
4              
5             =head1 Synopsis
6              
7             use Math::Cartesian::Product;
8              
9             cartesian {print "@_\n"} [qw(a b c)], [1..2];
10              
11             # a 1
12             # a 2
13             # b 1
14             # b 2
15             # c 1
16             # c 2
17              
18             cartesian {print "@_\n"} ([0..1]) x 8;
19              
20             # 0 0 0 0 0 0 0 0
21             # 0 0 0 0 0 0 0 1
22             # 0 0 0 0 0 0 1 0
23             # ...
24             # 1 1 1 1 1 1 1 0
25             # 1 1 1 1 1 1 1 1
26              
27             =cut
28              
29             package Math::Cartesian::Product;
30              
31 1     1   22233 use Carp;
  1         3  
  1         89  
32 1     1   6 use strict;
  1         2  
  1         386  
33              
34 30     30 0 6979 sub cartesian(&@) # Generate the cartesian product of zero or more lists
35             {my $s = shift; # Subroutine to call to process each element of the product
36              
37 30         65 my @C = @_; # Lists to be multiplied
38 30         51 my @c = (); # Current element of cartesian product
39 30         40 my @P = (); # Cartesian product
40 30         37 my $n = 0; # Number of elements in product
41              
42             # return 0 if @C == 0; # Empty product per Philipp Rumpf
43              
44 30 50       72 @C == grep {ref eq 'ARRAY'} @C or croak("Arrays of things required by cartesian");
  47         161  
45              
46             # Generate each cartesian product when there are no prior cartesian products.
47              
48 30         37 my $p; $p = sub
  65744         113032  
49 2625868 100   2625868   3605781 {if (@c < @C)
50 65744         53958 {for(@{$C[@c]})
  2625840         2246341  
  2560124         4228151  
51             {push @c, $_;
52 2625840         3069313 &$p();
53 2625840         8724644 pop @c;
54             }
55             }
56             else
57             {my $p = [@c];
58 2560124 100       3593700 push @P, bless $p if &$s(@$p);
59             }
60 30         1825 };
61              
62             # Generate each cartesian product allowing for prior cartesian products.
63              
64 30         41 my $q; $q = sub
  10         23  
65 42 100   42   73 {if (@c < @C)
66 10 50       10 {for(@{$C[@c]})
  40         44  
  64         209  
67             {push @c, $_;
68 40         68 &$q();
69 40         1416 pop @c;
70             }
71             }
72             else
73 32         47 {my $p = [map {ref eq __PACKAGE__ ? @$_ : $_} @c];
74 32 100       69 push @P, bless $p if &$s(@$p);
75             }
76 30         116 };
77              
78             # Determine optimal method of forming cartesian products for this call
79              
80 30 100       58 if (grep {grep {ref eq __PACKAGE__} @$_} @C)
  47         61  
  258         418  
  2         6  
81 28         49 {&$q
82             }
83             else
84             {&$p
85             }
86              
87 30         92 $p = $q = undef; # Break memory loops per Philipp Rumpf
88             @P # Product
89 30         414966 }
90              
91             # Export details
92            
93             require 5;
94             require Exporter;
95              
96 1     1   6 use vars qw(@ISA @EXPORT $VERSION);
  1         6  
  1         130  
97              
98             @ISA = qw(Exporter);
99             @EXPORT = qw(cartesian);
100             $VERSION = '1.007'; # Monday 26 Jan 2015
101              
102             =head1 Description
103              
104             Generate the cartesian product of zero or more lists.
105              
106             Given two lists, say: [a,b] and [1,2,3], the cartesian product is the
107             set of all ordered pairs:
108              
109             (a,1), (a,2), (a,3), (b,1), (b,2), (b,3)
110              
111             which select their first element from all the possibilities listed in
112             the first list, and select their second element from all the
113             possibilities in the second list.
114              
115             The idea can be generalized to n-tuples selected from n lists. In
116             particular, the cartesian product of zero lists is the empty set, as is
117             the cartesian product of any set of lists which contain a list with no
118             elements.
119              
120             C takes the following parameters:
121              
122             1. A block of code to process each n-tuple. this code should return true
123             if the current n-tuple should be included in the returned value of the
124             C function, otherwise false.
125              
126             2. Zero or more lists.
127              
128             C returns an array of references to all the n-tuples
129             selected by the code block supplied as parameter 1.
130              
131             C croaks if you try to form the cartesian product of
132             something other than lists of things.
133              
134             The cartesian product of lists A,B,C is associative, that is:
135              
136             (A X B) X C = A X (B X C)
137              
138             C respects associativity by allowing you to include a
139             cartesian product produced by an earlier call to C in the
140             set of lists whose cartesian product is to be formed, at the cost of a
141             performance penalty if this option is chosen.
142              
143             use Math::Cartesian::Product;
144            
145             my $a = [qw(a b)];
146             my $b = [cartesian {1} $a, $a];
147             cartesian {print "@_\n"} $b, $b;
148              
149             # a a a a
150             # a a a b
151             # a a b a
152             # ...
153            
154              
155             C is easy to use and fast. It is written in 100% Pure Perl.
156              
157              
158             =head1 Export
159              
160             The C function is exported.
161              
162             =head1 Installation
163              
164             Standard Module::Build process for building and installing modules:
165              
166             perl Build.PL
167             ./Build
168             ./Build test
169             ./Build install
170              
171             Or, if you're on a platform (like DOS or Windows) that doesn't require
172             the "./" notation, you can do this:
173              
174             perl Build.PL
175             Build
176             Build test
177             Build install
178              
179             =head1 Author
180              
181             PhilipRBrenan@appaapps.com
182              
183             http://www.appaapps.com
184              
185             =head1 Acknowledgements
186              
187             With much help and good natured advice from Philipp Rumpf to whom I am greatly indebted.
188              
189             =head1 See Also
190              
191             =over
192              
193             =item L
194              
195             =item L
196              
197             =item L
198              
199             =item L
200              
201             =back
202              
203             =head1 Copyright
204              
205             Copyright (c) 2009 Philip R Brenan.
206              
207             This module is free software. It may be used, redistributed and/or
208             modified under the same terms as Perl itself.
209              
210             =cut