File Coverage

blib/lib/Math/MagicSquare.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             #
2             # MagicSquare.pm, version 2.04 13 Dec 2003
3             #
4             # Copyright (c) 2003 Fabrizio Pivari Italy
5             # fabrizio@pivari.com
6             #
7             # Free usage under the same Perl Licence condition.
8             #
9              
10             package Math::MagicSquare;
11              
12 2     2   1711 use Carp;
  2         4  
  2         225  
13 2     2   5848 use GD;
  0            
  0            
14             use strict;
15             use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION);
16              
17             use Exporter();
18             @ISA= qw(Exporter);
19             @EXPORT=qw();
20             @EXPORT_OK=qw(new check print printhtml rotation reflection);
21             $VERSION='2.04';
22              
23             sub new {
24             my $type = shift;
25             my $self = [];
26             my $len = scalar(@{$_[0]});
27             my $numelem = 0;
28             for (@_) {
29             push(@{$self}, [@{$_}]);
30             $numelem += scalar(@{$_});
31             }
32             croak "Math::MagicSquare::new(): number of rows and columns must be equal"
33             if ($numelem != $len*$len);
34             bless $self, $type;
35             }
36              
37             sub check {
38             my $self = shift;
39             my $i=0; my $j=0;
40             my $line1=0; my $line2=0; my $diag1=0; my $diag2=0; my $SUM=0;
41             my $sms=1;
42             my $len = scalar(@{$self});
43              
44             # Magic Constant for a Magic Square 1,2,...,n
45             my $sum=$len*($len*$len+1)/2;
46             # Generic Magic Constant
47             for ($i=0;$i<$len;$i++) {
48             $SUM+=$self->[$i][0];
49             }
50             if ($SUM != $sum) {$sum=$SUM;}
51             # Check lines and columns
52             for ($i=0;$i<$len;$i++) {
53             $j=0; $line1=0; $line2=0;
54             for ($j=0;$j<$len;$j++) {
55             $line1+=$self->[$i][$j];
56             $line2+=$self->[$j][$i];
57             }
58             if ($line1 != $sum || $line2 != $sum) {
59             # This isn't a Magic
60             return(0);
61             }
62             }
63             # Check diagonals and broken diagonals
64             for ($j=0;$j<$len;$j++) {
65             $i=0; $diag1=0; $diag2=0;
66             for ($i=0;$i<$len;$i++) {
67             $diag1+=$self->[$i][($i+$j)%$len];
68             $diag2+=$self->[$len-1-$i][($i+$j)%$len];
69             }
70             if ($j == 0) {
71             if ($diag1 != $sum || $diag2 != $sum) {
72             # This is a Semimagic Square
73             return(1);
74             }
75             } else {
76             if ($diag1 != $sum || $diag2 != $sum) {
77             # This is a Magic Square
78             return(2);
79             }
80             }
81             }
82             # This is a Panmagic Square
83             return(3);
84             }
85              
86             sub print {
87             my $self = shift;
88             my $initialtext = shift;
89             my $i=0; my $j=0;
90             my $len = scalar(@{$self});
91            
92             print "$initialtext\n" if $initialtext;
93             print @_ if scalar(@_);
94             for ($j=0;$j<$len;$j++) {
95             for ($i=0;$i<$len;$i++) {
96             printf "%5d ", $self->[$j][$i];
97             }
98             print "\n";
99             }
100             }
101              
102             sub printhtml {
103             my $self = shift;
104             my $i=0; my $j=0;
105             my $len = scalar(@{$self});
106              
107             print qq!\n!; \n"; \n"; \n";
108             for ($j=0;$j<$len;$j++) {
109             print "
110             for ($i=0;$i<$len;$i++) {
111             print "$self->[$j][$i]
112             }
113             print "
114             }
115             print "
\n";
116             }
117              
118             sub printimage {
119             my $self = shift;
120             my $i=0; my $j=0;
121             my $len = scalar(@{$self});
122              
123             my $CELLGRIDSIZE = 31;
124             my $GRIDSIZE = 8+($len -1)*2+$len*$CELLGRIDSIZE;
125             my $im=new GD::Image($GRIDSIZE,$GRIDSIZE);
126             my $bg=$im->colorAllocate(255,255,255);
127             my $fg=$im->colorAllocate(0,0,0);
128              
129             # GRID
130             # $im->transparent($bg);
131             $im->filledRectangle(0,0,255,255,$bg);
132             $im->filledRectangle(0,0,4,$GRIDSIZE,$fg);
133             $im->filledRectangle(0,0,$GRIDSIZE,4,$fg);
134             my $tmp = $GRIDSIZE -5;
135             $im->filledRectangle($tmp,0,$GRIDSIZE,$GRIDSIZE,$fg);
136             $im->filledRectangle(0,$tmp,$GRIDSIZE,$GRIDSIZE,$fg);
137             my $xy = 4 + $CELLGRIDSIZE;
138             my $xy2 = $xy +2;
139             for (1..$len-1)
140             {
141             $im->filledRectangle($xy,0,$xy2,$GRIDSIZE,$fg);
142             $im->filledRectangle(0,$xy,$GRIDSIZE,$xy2,$fg);
143             $xy = $xy2 + $CELLGRIDSIZE;
144             $xy2 = $xy + 2;
145             }
146              
147             # NUMBERS
148             my $x1 = 4 + 8;
149             my $y1 = 4 + 9;
150             $j=0;
151             for ($j=0;$j<$len;$j++)
152             {
153             $i=0;
154             for ($i=0;$i<$len;$i++)
155             {
156             # to hit the centre with numbers < -9
157             if ($self->[$j][$i] < -9) { $x1 = $x1 - 3; }
158             # to hit the centre with numbers between -9 and -1
159             if ($self->[$j][$i] < 0 && $self->[$j][$i] > -10) { $x1 = $x1 - 2; }
160             # to hit the centre with numbers between 0 and 9
161             if ($self->[$j][$i] < 10 && $self->[$j][$i] >= 0) { $x1 = $x1 + 4; }
162             # to hit the centre with numbers > 99
163             if ($self->[$j][$i] > 99) { $x1 = $x1 - 4; }
164             $im->string(gdLargeFont,$x1,$y1,"$self->[$j][$i]",$fg);
165             $x1 = $x1 + $CELLGRIDSIZE + 2;
166             if ($self->[$j][$i] < -9) { $x1 = $x1 + 3; }
167             if ($self->[$j][$i] < 0 && $self->[$j][$i] > -10) { $x1 = $x1 + 2; }
168             if ($self->[$j][$i] < 10 && $self->[$j][$i] >= 0) { $x1 = $x1 - 4; }
169             if ($self->[$j][$i] > 99) { $x1 = $x1 + 4; }
170             }
171             $x1 = 4 + 8;
172             $y1 = $y1 + $CELLGRIDSIZE + 2;
173             }
174              
175             binmode STDOUT;
176             print $im -> png;
177             }
178              
179             sub rotation {
180             my $self = shift;
181             my $i=0; my $j=0;
182             my @TMP;
183             my $len = scalar(@{$self});
184              
185             for ($j=0;$j<$len;$j++) {
186             for ($i=0;$i<$len;$i++) {
187             $TMP[$j][$i]=$self->[$j][$i];
188             }
189             }
190             for ($j=0;$j<$len;$j++) {
191             for ($i=0;$i<$len;$i++) {
192             $self->[$j][$i]=$TMP[$len-1-$i][$j];
193             }
194             }
195             }
196              
197             sub reflection {
198             my $self = shift;
199             my $i=0; my $j=0;
200             my @TMP;
201             my $len = scalar(@{$self});
202              
203             for ($j=0;$j<$len;$j++) {
204             for ($i=0;$i<$len;$i++) {
205             $TMP[$j][$i]=$self->[$j][$i];
206             }
207             }
208             for ($j=0;$j<$len;$j++) {
209             for ($i=0;$i<$len;$i++) {
210             $self->[$i][$j]=$TMP[$i][$len-1-$j];
211             }
212             }
213             }
214              
215             1;
216              
217             __END__