File Coverage

blib/lib/Math/MagicSquare/Generator.pm
Criterion Covered Total %
statement 46 66 69.7
branch 11 18 61.1
condition 5 15 33.3
subroutine 7 12 58.3
pod 8 8 100.0
total 77 119 64.7


line stmt bran cond sub pod time code
1             package Math::MagicSquare::Generator;
2 1     1   300205 use strict;
  1         2  
  1         50  
3 1     1   8 use Carp;
  1         3  
  1         88  
4 1     1   6 use vars qw($VERSION);
  1         17  
  1         1110  
5              
6             $VERSION = '0.01';
7              
8             sub _sum {
9 4520     4520   4925 my $sum = 0;
10 4520         193061 $sum += $_ for @_;
11 4520         27598 return $sum
12             }
13              
14             sub new {
15 20     20 1 16083 my ($class, %opt) = @_;
16 20   50     100 $opt{size} ||= 5;
17 20   50     163 $opt{start} ||= 1;
18 20   50     94 $opt{step} ||= 1;
19 20 50 33     189 croak "Size needs to be a positive, odd integer"
      33        
20             unless $opt{size} > 0 and
21             $opt{size} % 2 and
22             $opt{size} == int($opt{size});
23 2230         52570 my $self = [
24             map {
25 20         147 [ (undef) x $opt{size} ]
26             } 1..$opt{size}
27             ];
28 20         183 my $value = $opt{start};
29 20         103 my $halv = int(@$self / 2);
30 20         83 for my $start_x (-$halv..$halv) {
31 2230         2701 my $x = $start_x - 1;
32 2230         4217 my $y = $x + @$self + 1;
33 2230         5298 for (1 .. @$self) {
34 324452 100       525764 $x = $x - @$self if ++$x > $#$self;
35 324452 100       542760 $y = $y - @$self if --$y > $#$self;
36 324452         438027 $self->[$y][$x] = $value;
37 324452         375756 $value += $opt{step};
38             }
39             }
40 20         351 return bless $self, $class;
41             }
42              
43             sub hflip {
44 0     0 1 0 my ($self) = @_;
45 0         0 my $clone;
46 0         0 push @$clone, [ reverse @$_ ] for @$self;
47 0         0 return bless $clone, ref $self;
48             }
49              
50             sub vflip {
51 0     0 1 0 my ($self) = @_;
52 0         0 my $clone;
53 0         0 push @$clone, [ @$_ ] for reverse @$self;
54 0         0 return bless $clone, ref $self;
55             }
56              
57             sub sum {
58 20     20 1 35 my ($self) = @_;
59 20         28 return _sum( @{ $self->[0] } );
  20         164  
60             }
61              
62             sub check {
63 20     20 1 55 my ($self) = @_;
64 20         84 my $sum = $self->sum;
65             # Horizontals
66 20         238 for (@$self[1..$#$self]) {
67 2210 50       3781 return undef if @$_ > @$self; # undef if not square
68 2210 50       13291 return undef if _sum(@$_) != $sum;
69             }
70             # Verticals
71 20         153 for my $x (0..$#$self) {
72 2230 50       138703 return undef if _sum(map $self->[$_][$x], 0..$#$self) != $sum;
73             }
74             # Diagonals
75 20 50       1032 return undef if _sum(map $self->[$_][$_], 0..$#$self) != $sum;
76 20 50       12367 return undef if _sum(map $self->[$#$self - $_][$_], 0..$#$self) != $sum;
77             # Duplicates
78 20         143 my %seen;
79 20         390638 $seen{$_}++ for map @$_, @$self;
80 20 50       83774 return undef if _sum(values %seen) != keys %seen;
81             # Passed all tests!
82 20         129756 return $sum;
83             }
84              
85             sub as_string {
86 0     0 1   my ($self) = @_;
87 0           my $max = 0;
88 0   0       length > $max and $max = length for map @$_, @$self;
89 0           return map { join(' ', map {' 'x($max - length) . $_} @$_) . "\n" } @$self;
  0            
  0            
90             }
91              
92             sub as_html {
93 0     0 1   my ($self) = @_;
94 0           return "\n" . join("\n", ' } @$self) .
95 0           map { '
' . join('', @$_) . '
96             "\n
\n";
97             }
98              
99             sub as_csv {
100 0     0 1   my ($self) = @_;
101 0           return join("\n", map { join ',', @$_ } @$self) . "\n";
  0            
102             }
103              
104             1;
105              
106             __END__