File Coverage

blib/lib/List/PowerSet.pm
Criterion Covered Total %
statement 26 26 100.0
branch 8 8 100.0
condition n/a
subroutine 6 6 100.0
pod 2 2 100.0
total 42 42 100.0


line stmt bran cond sub pod time code
1             package List::PowerSet;
2              
3             # $Id: PowerSet.pm,v 1.4 2004/03/07 22:44:43 nik Exp $
4              
5 1     1   24031 use strict;
  1         2  
  1         42  
6 1     1   6 use warnings;
  1         2  
  1         33  
7              
8 1     1   5 use base qw(Exporter);
  1         13  
  1         442  
9              
10             our @EXPORT_OK = qw(powerset powerset_lazy);
11             our $VERSION = '0.01';
12              
13             =head1 NAME
14              
15             List::PowerSet - generate the power set of a list
16              
17             =head1 SYNOPSIS
18              
19             use List::PowerSet qw(powerset powerset_lazy);
20              
21             my $ps = powerset(qw(1 2 3));
22              
23             my $ps_iterator = powerset_lazy(1 .. 1_000);
24             while(my $set = $ps_iterator->()) {
25             # $set is the next powerset entry
26             }
27              
28             =head1 DESCRIPTION
29              
30             Suppose you have a list L. The power set of such a list is a list of
31             all the sublists that you can obtain from L by deleting elements from it.
32             For example, the power set of (1, 2, 3) is the list of lists ((), (1),
33             (2), (3), (1, 2), (1, 3), (2, 3), (1, 2, 3)), in some order.
34              
35             C provides two functions (which are not exported by default,
36             you have to ask for them) to generate power sets.
37              
38             =cut
39              
40             =head1 FUNCTIONS
41              
42             =head2 B
43              
44             Given a list, C returns an array reference of array references,
45             each referring to a different subset in the powerset of the input list.
46              
47             my $ps = powerset(qw(1 2 3));
48              
49             # $ps == [ [1, 2, 3],
50             # [ 2, 3],
51             # [1, 3],
52             # [ 3],
53             # [1, 2 ],
54             # [ 2 ],
55             # [1 ],
56             # [ ] ];
57              
58             =cut
59              
60             # mjd's powerset implementation. See http://perl.plover.com/LOD/199803.html
61             # for more details
62             sub powerset {
63 4 100   4 1 517 return [[]] if @_ == 0;
64 3         5 my $first = shift;
65 3         10 my $pow = &powerset;
66 3         6 [ map { [$first, @$_ ], [ @$_] } @$pow ];
  7         23  
67             }
68              
69             =head2 B
70              
71             Given even a moderately sized input list, C will have to
72             generate a huge result list, taking time and memory to generate. A 20
73             element input list to C will generate a result list containing
74             1,048,576 references to other arrays, on average containing 10 items.
75              
76             C takes the same input list as C, and returns
77             a subroutine reference. Every time you call through this reference an
78             array reference to a different subset of the powerset is generated and
79             returned.
80              
81             =cut
82              
83             # mjd's implementation, from personal e-mail
84             sub powerset_lazy {
85 1     1 1 3255 my @set = @_;
86 1         5 my @odometer = (1) x @set;
87 1         2 my $FINISHED;
88             return sub {
89 9 100   9   6307 return if $FINISHED;
90 8         12 my @result;
91 8         10 my $adjust = 1;
92 8         20 for (0 .. $#odometer) {
93 24 100       50 push @result, $set[$_] if $odometer[$_];
94 24 100       64 $adjust = $odometer[$_] = 1 - $odometer[$_] if $adjust;
95             }
96 8         15 $FINISHED = (@result == 0);
97 8         23 \@result;
98 1         7 };
99             }
100              
101              
102             =head1 AUTHORS
103              
104             Mark Jason Dominus , Nik Clayton
105              
106             The original code was written by Mark.
107              
108             The module was written by Nik, who discovered mjd's code after failing
109             to find a powerset implementation on CPAN. With mjd's permission he
110             packaged it so that others can easily make use of it.
111              
112             Copyright 2004 Mark Jason Dominus, and Nik Clayton. All Rights Reserved.
113              
114             This program is free software; you can redistribute it
115             and/or modify it under the same terms as Perl itself.
116              
117             =head1 BUGS
118              
119             None known.
120              
121             Bugs should be reported to via the CPAN RT system.
122             L.
123              
124             =cut
125              
126             1;