File Coverage

blib/lib/Acme/Sort/Bogosort.pm
Criterion Covered Total %
statement 32 32 100.0
branch 11 12 91.6
condition n/a
subroutine 9 9 100.0
pod 2 3 66.6
total 54 56 96.4


line stmt bran cond sub pod time code
1             package Acme::Sort::Bogosort;
2              
3 1     1   39768 use 5.010;
  1         4  
  1         41  
4              
5 1     1   85 use strict;
  1         5  
  1         36  
6 1     1   5 use warnings;
  1         7  
  1         43  
7              
8 1     1   1522 use parent qw/Exporter/;
  1         624  
  1         6  
9 1     1   57 use Carp 'croak';
  1         3  
  1         57  
10              
11 1     1   6 use List::Util qw/shuffle/;
  1         2  
  1         530  
12              
13             our @EXPORT = qw/bogosort/;
14              
15             our $VERSION = '0.05';
16              
17              
18              
19             # bogosort()
20             # Usage:
21             # Sort a list in standard string comparison order.
22             #
23             # my @sorted = bogosort( @unsorted );
24             #
25             # Sort a list in ascending numerical order:
26             # sub compare { return $_[0] <=> $_[1] };
27             # my @sorted = bogosort( \&compare, @unsorted );
28             #
29             # Warning: Average case is O( (e-1) * n! ).
30             # Warning: Worst case approaches O(INF).
31             #
32             # bogosort() is exported automatically upon use.
33              
34             sub bogosort {
35 2 100   2 1 2393 my $compare = ref( $_[0] ) =~ /CODE/
36             ? shift
37             : \&compare;
38 2 50       9 return @_ if @_ < 2;
39 2         9 my @list = @_;
40 2         6 @list = shuffle( @list ) while not is_ordered( $compare, \@list );
41 2         16 return @list;
42             }
43              
44              
45              
46             # Internal use, not exported. Verifies order based on $compare->().
47             sub is_ordered {
48 98     98 0 1939 my ( $compare, $listref ) = @_;
49 98 100       433 ref( $compare ) =~ /CODE/
50             or croak "is_ordered() expects a coderef as first arg.";
51 97 100       2719 ref( $listref ) =~ /ARRAY/
52             or croak "is_ordered() expects an arrayref as second arg.";
53 96         100 foreach( 0 .. $#{$listref} - 1 ) {
  96         188  
54 174 100       592 return 0
55             if $compare->( $listref->[ $_ ], $listref->[ $_ + 1 ] ) > 0;
56             }
57 3         17 return 1;
58             }
59              
60             # Default compare() is ascending standard string comparison order.
61             sub compare {
62 167 100   167 1 3902 croak "compare() requires two args."
63             unless scalar @_ == 2;
64 166         1051 return $_[0] cmp $_[1];
65             }
66              
67              
68             =head1 NAME
69              
70             Acme::Sort::Bogosort - Implementation of a Bogosort (aka 'stupid sort' or 'slowsort').
71              
72             =head1 VERSION
73              
74             Version 0.05
75              
76             =head1 SYNOPSIS
77              
78             The Bogosort is a sort that is based on the "generate and test" paradigm. It works by
79             first testing whether the input is in sorted order. If so, return the list. But if not,
80             randomly shuffle the input and test again. Repeat until the shuffle comes back sorted.
81              
82             use Acme::Sort::Bogosort;
83              
84             my @unsorted = qw/ E B A C D /;
85             my @ascending = bogosort( @unsorted );
86            
87             my @descending = bogosort(
88             sub{ return $_[1] cmp $_[0]; },
89             @unsorted
90             );
91              
92             The Bogosort has a worst case of O(INF), though as time approaches infinity the odds of not
93             finding a solution decline toward zero (assuming a good random number generator). The average
94             case is O( (n-1) * n! ). The n! term signifies how many shuffles will be required to obtain
95             a sorted result in the average case. However, there is no guarantee that any particular sort
96             will come in anywhere near average.
97              
98             Keep in mind that a list of five items consumes an average of 5!, or 120 iterations. 10! is
99             3,628,800 shuffles. Also keep in mind that each shuffle itself is an O(n-1) operation.
100             Unless you need to heat a cold office with your processor avoid sorts on large data sets.
101              
102             =head1 EXPORT
103              
104             Always exports one function: C.
105              
106             =head1 SUBROUTINES/METHODS
107              
108             =head2 bogosort( @unsorted )
109              
110             Accepts a list as a parameter and returns a sorted list.
111              
112             If the first parameter is a reference to a subroutine, it will be used as the
113             comparison function.
114              
115             The Bogosort is probably mostly useful as a teaching example of a terrible sort
116             algorithm. There are approximately 1e80 atoms in the universe. A sort list of
117             59 elements will gain an average case solution of 1e80 iterations, with a worst
118             case approaching infinite iterations to find a solution. Anything beyond just a
119             few items takes a considerable amount of work.
120              
121             Each iteration checks first to see if the list is in order. Here a comparatively
122             minor optimization is that the first out-of-order element will short-circuit the
123             check. That step has a worst case of O(n), and average case of nearly O(1).
124             That's the only good news. Once it is determined that the list is out
125             of order, the entire list is shuffled (an O(n) operation). Then the test happens
126             all over again, repeating until a solution is happened across by chance.
127              
128             There is a potential for this sort to never finish, since a typical random number
129             synthesizer does not generate an infinitely non-repeating series. Because this
130             algorithm has the capability of producing O(INF) iterations, it would need an
131             infinite source of random numbers to find a solution in any given dataset.
132              
133             Small datasets are unlikely to encounter this problem, but as the dataset grows,
134             so does the propensity for running through the entire set of pseudo-random numbers
135             generated by Perl's rand() for a given seed. None of this really matters, of course,
136             as no sane individual would ever use this for any serious sorting work.
137              
138             Not every individual is sane.
139              
140             =cut
141              
142              
143             =head2 compare( $a, $b )
144              
145             By passing a subref as the first parameter to C, the user is able to
146             manipulate sort orders just as is done with Perl's built in C< sort { code } @list >
147             routine.
148              
149             The comparison function is easy to implement using Perl's C<< <=> >> and C< cmp >
150             operators, but any amount of creativity is ok so long as return values are negative
151             for "Order is ok", positive for "Order is not ok", and 0 for "Terms are equal
152             (Order is ok)".
153              
154             =cut
155              
156              
157             =head1 AUTHOR
158              
159             David Oswald, C<< >>
160              
161             =head1 BUGS
162              
163             Please report any bugs or feature requests to C, or through
164             the web interface at L. I will be notified, and then you'll
165             automatically be notified of progress on your bug as I make changes.
166              
167              
168              
169              
170             =head1 SUPPORT
171              
172             You can find documentation for this module with the perldoc command.
173              
174             perldoc Acme::Sort::Bogosort
175              
176              
177             You can also look for information at:
178              
179             =over 4
180              
181             =item * RT: CPAN's request tracker (report bugs here)
182              
183             L
184              
185             =item * AnnoCPAN: Annotated CPAN documentation
186              
187             L
188              
189             =item * CPAN Ratings
190              
191             L
192              
193             =item * Search CPAN
194              
195             L
196              
197             =back
198              
199              
200             =head1 ACKNOWLEDGEMENTS
201              
202             L - A nice Wikipedia article on the Bogosort.
203              
204             =head1 LICENSE AND COPYRIGHT
205              
206             Copyright 2011 David Oswald.
207              
208             This program is free software; you can redistribute it and/or modify it
209             under the terms of either: the GNU General Public License as published
210             by the Free Software Foundation; or the Artistic License.
211              
212             See http://dev.perl.org/licenses/ for more information.
213              
214              
215             =cut
216              
217             1; # End of Acme::Sort::Bogosort