File Coverage

blib/lib/Algorithm/Partition.pm
Criterion Covered Total %
statement 45 47 95.7
branch 12 14 85.7
condition 2 3 66.6
subroutine 7 7 100.0
pod 1 1 100.0
total 67 72 93.0


line stmt bran cond sub pod time code
1             package Algorithm::Partition;
2              
3 2     2   67693 use warnings;
  2         6  
  2         79  
4 2     2   13 use strict;
  2         5  
  2         73  
5 2     2   2344 use integer;
  2         31  
  2         12  
6              
7             =head1 NAME
8              
9             Algorithm::Partition - Partition a set of integers.
10              
11             =head1 VERSION
12              
13             Version 0.04
14              
15             =cut
16              
17             our $VERSION = '0.04';
18              
19             =head1 SYNOPSIS
20              
21             use Algorithm::Partition qw(partition);
22              
23             my ($one, $two) = partition(2, 4, 1, 5, 8, 16);
24             unless (defined($one)) {
25             print "Error: $two"; # now $two is an error
26             } else {
27             print "Set 1: @$one\n";
28             print "Set 2: @$two\n";
29             }
30              
31             =cut
32              
33 2     2   115 use base qw(Exporter);
  2         4  
  2         325  
34             our @EXPORT_OK = qw(partition);
35              
36             =head1 EXPORT
37              
38             This module does not export anything by default. You can export
39             function B:
40              
41             use Algorith::Partition qw(partition);
42              
43             =head1 DESCRIPTION
44              
45             This module implements an algorithm to see whether a set of integers can
46             be split into two sets such that the sums of integers in one set is equal
47             to the sum of integers in the other set.
48              
49             =head1 FUNCTIONS
50              
51             =head2 partition(@integers);
52              
53             Given a list of integers, this function will return two values. If the
54             first value is C, then no solution was found and the second value
55             is a string explaining why. Otherwise, two array references are returned
56             which point to the two resulting sets.
57              
58             The algorithm is meant for relatively small sets of integers with relatively
59             small values. Beware.
60              
61             =cut
62              
63 2     2   14 use constant TOP => 1;
  2         4  
  2         191  
64 2     2   11 use constant LEFT => 2;
  2         5  
  2         1203  
65              
66             sub partition {
67 4     4 1 2668 my @set = @_;
68              
69 4 100       17 unless (@set > 0) {
70 1         5 return (undef, "the set should be non-empty");
71             }
72              
73 3         5 my $size = 0;
74 3         13 $size += $_ for @set;
75              
76 3 100       9 if ($size & 1) {
77 2         11 return (undef, "no solution found: $size is odd");
78             }
79              
80 1         3 $size >>= 1;
81              
82 1         3 my @table;
83              
84             # generate the first row
85 1         4 $table[0] = [ map {[ 0 ]} (0 .. $size) ];
  6         27  
86 1         6 $table[0][0] = [ 1, TOP ];
87 1         4 $table[0][$set[0]] = [ 1, LEFT ];
88              
89             # generate the rest of the table
90 1         10 for (my $i = 1; $i < @set; ++$i) {
91 3         10 for (my $j = 0; $j <= $size; ++$j) {
92 18 100 66     67 if ($table[$i - 1][$j][0]) {
    100          
93 12         49 $table[$i][$j] = [ 1, TOP ];
94             } elsif ($j - $set[$i] >= 0 &&
95             $table[$i - 1][$j - $set[$i]][0])
96             {
97 4         18 $table[$i][$j] = [ 1, LEFT ],
98             } else {
99 2         13 $table[$i][$j] = [ 0, 0 ];
100             }
101              
102             #warn "$i:$j: ", $table[$i][$j][0], "\n";
103             }
104             }
105              
106 1 50       5 unless ($table[-1][-1][0]) {
107 0         0 return (undef, "no solution found");
108             }
109              
110 1         2 my (@one, @two);
111              
112 1         6 for (my ($i, $j) = (@set - 1, $size); $i >= 0; --$i) {
113 4 100       14 if (LEFT == $table[$i][$j][1]) {
    50          
114 2         4 push @one, $set[$i];
115 2         7 $j -= $set[$i];
116             } elsif (TOP == $table[$i][$j][1]) {
117 2         8 push @two, $set[$i];
118             } else {
119 0         0 die "Programmer error. Please report this bug.";
120             }
121             }
122              
123 1         19 return (\@one, \@two);
124             }
125              
126             =head1 AUTHOR
127              
128             Dmitri Tikhonov, C<< >>
129              
130             =head1 BUGS
131              
132             Please report any bugs or feature requests to
133             C, or through the web interface at
134             L.
135             I will be notified, and then you'll automatically be notified of progress on
136             your bug as I make changes.
137              
138             =head1 SUPPORT
139              
140             You can find documentation for this module with the perldoc command.
141              
142             perldoc Algorithm::Partition
143              
144             You can also look for information at:
145              
146             =over 4
147              
148             =item * AnnoCPAN: Annotated CPAN documentation
149              
150             L
151              
152             =item * CPAN Ratings
153              
154             L
155              
156             =item * RT: CPAN's request tracker
157              
158             L
159              
160             =item * Search CPAN
161              
162             L
163              
164             =back
165              
166             =head1 ACKNOWLEDGEMENTS
167              
168             NJIT, Professor Joseph Leung, and the NP-Completeness course.
169              
170             =head1 COPYRIGHT & LICENSE
171              
172             Copyright 2007 Dmitri Tikhonov, all rights reserved.
173              
174             This program is free software; you can redistribute it and/or modify it
175             under the same terms as Perl itself.
176              
177             =cut
178              
179             1; # End of Algorithm::Partition