Advent Calendar 2021
| Day 16 | Day 17 | Day 18 |
The gift is presented by Walt Mankowski. Today he is talking about his solution to “The Weekly Challenge - 089”. This is re-produced for Advent Calendar 2021 from the original post by Walt Mankoswki
.
Task #2: Magical Matrix
Write a script to display matrix as below with numbers 1 - 9
. Please make sure numbers are used once.
[ a b c ]
[ d e f ]
[ g h i ]
So that it satisfies the following:
a + b + c = 15
d + e + f = 15
g + h + i = 15
a + d + g = 15
b + e + h = 15
c + f + i = 15
a + e + i = 15
c + e + g = 15
For this task we need to create a 3 x 3
magic square; i.e. a matrix where each row, column, and diagonal sums to the same value. We’re restricted to the numbers 1-9
, so the sums should all be 15
.
This is trivial in Matlab
and Octave
since there’s a built in function to create magic squares, so all we need to do is say
magic(3)
We have to do a bit more work in Perl
, but fortunately there’s a simple algorithm for creating these sorts of magic squares called the Siamese
method. It works for any m x m
magic square where m is odd
. Here’s the algorithm:
1. Start with a 1 in the middle column of the top row.
2. For each subsequent number, try to move to the cell to the northeast (1 row up and 1 column right), wrapping around to the left and bottom when we reach the edge.
3. If that cell is occupied, move one 1 down (wrapping around to the top if we’re on the bottom row) instead of moving to the northeast.
This is easy to do in Perl
, and we don’t even have to initialize the matrix.
my @m;
my $m = 3;
my $r = 0;
my $c = 1;
# fill in the magic square using the Siamese method
for my $i (1..9) {
$m[$r][$c] = $i;
my $r1 = ($r - 1) % $m;
my $c1 = ($c + 1) % $m;
if (defined $m[$r1][$c1]) {
$r = ($r + 1) % $m;
} else {
$r = $r1;
$c = $c1;
}
}
If you have any suggestion then please do share with us perlweeklychallenge@yahoo.com.