Cartesian product of two or more lists: Difference between revisions
Content added Content deleted
(→{{header|F Sharp|F#}}: Claim the extra credit) |
SqrtNegInf (talk | contribs) (Added Perl example) |
||
Line 1,616: | Line 1,616: | ||
val product'' : 'a list tuple -> 'a tuple list = <fun> |
val product'' : 'a list tuple -> 'a tuple list = <fun> |
||
</lang> |
</lang> |
||
=={{header|Perl}}== |
|||
==== Iterative ==== |
|||
Nested loops, with a short-circuit to quit early if any term is an empty set. |
|||
<lang perl>sub cartesian { |
|||
my $sets = shift @_; |
|||
for (@$sets) { return [] unless @$_ } |
|||
my $products = [[]]; |
|||
for my $set (reverse @$sets) { |
|||
my $partial = $products; |
|||
$products = []; |
|||
for my $item (@$set) { |
|||
for my $product (@$partial) { |
|||
push @$products, [$item, @$product]; |
|||
} |
|||
} |
|||
} |
|||
$products; |
|||
} |
|||
sub product { |
|||
my($s,$fmt) = @_; |
|||
my $tuples; |
|||
for $a ( @{ cartesian( \@$s ) } ) { $tuples .= sprintf "($fmt) ", @$a; } |
|||
$tuples . "\n"; |
|||
} |
|||
print |
|||
product([[1, 2], [3, 4] ], '%1d %1d' ). |
|||
product([[3, 4], [1, 2] ], '%1d %1d' ). |
|||
product([[1, 2], [] ], '%1d %1d' ). |
|||
product([[], [1, 2] ], '%1d %1d' ). |
|||
product([[1,2,3], [30], [500,100] ], '%1d %1d %3d' ). |
|||
product([[1,2,3], [], [500,100] ], '%1d %1d %3d' ). |
|||
product([[1776,1789], [7,12], [4,14,23], [0,1]], '%4d %2d %2d %1d')</lang> |
|||
{{out}} |
|||
<pre>(1 3) (1 4) (2 3) (2 4) |
|||
(3 1) (3 2) (4 1) (4 2) |
|||
(1 30 500) (1 30 100) (2 30 500) (2 30 100) (3 30 500) (3 30 100) |
|||
(1776 7 4 0) (1776 7 4 1) (1776 7 14 0) (1776 7 14 1) (1776 7 23 0) (1776 7 23 1) (1776 12 4 0) (1776 12 4 1) (1776 12 14 0) (1776 12 14 1) (1776 12 23 0) (1776 12 23 1) (1789 7 4 0) (1789 7 4 1) (1789 7 14 0) (1789 7 14 1) (1789 7 23 0) (1789 7 23 1) (1789 12 4 0) (1789 12 4 1) (1789 12 14 0) (1789 12 14 1) (1789 12 23 0) (1789 12 23 1)</pre> |
|||
==== Glob ==== |
|||
This being Perl, there's more than one way to do it. A quick demonstration of how <code>glob</code>, more typically used for filename wildcard expansion, can solve the task. |
|||
<lang perl>$tuples = [ map { [split /:/] } glob '{1,2,3}:{30}:{500,100}' ]; |
|||
for $a (@$tuples) { printf "(%1d %2d %3d) ", @$a; }</lang> |
|||
{{out}} |
|||
<pre>(1 30 500) (1 30 100) (2 30 500) (2 30 100) (3 30 500) (3 30 100)</pre> |
|||
=={{header|Perl 6}}== |
=={{header|Perl 6}}== |