Magic squares/Raku
Rather than having multiple examples for different orders of magic square, this will generate a magic square for any valid n x n grid. Invoke at the command line and pass in the desired size as a parameter.
See:
- Magic squares of odd order#Perl 6
- Magic squares of singly even order#Perl 6
- Magic squares of doubly even order#Perl 6
<lang perl6>sub MAIN (Int $n where {$n > 0}) {
my @sq; my $i = 1; gen-sq($n);
say .fmt("%{$i.chars}d", ' ') for @sq;
say "\nThe magic number is ", [+] @sq[0].list;
multi sub gen-sq (2) { note "Sorry, can not generate a 2 x 2 magic square." and exit; }
multi sub gen-sq ($n where {$n % 2}) { my $x = $n/2; my $y = 0; @sq[($i % $n ?? $y-- !! $y++) % $n][($i % $n ?? $x++ !! $x) % $n] = $i++ for ^$n²; }
multi sub gen-sq ($n where {$n %% 4}) { my $x = 0; my $y = 0; @sq[$i % $n ?? $y !! $y++][($i-1) % $n] = $i++ for ^$n²; my $t; for 0 ..^ $n div 4 -> $r { for $n div 4 ..^ $n - $n div 4 -> $c { (@sq[$r;$c], @sq[$n-1-$r;$n-1-$c]) = (@sq[$n-1-$r;$n-1-$c], @sq[$r;$c]); (@sq[$c;$r], @sq[$n-1-$c;$n-1-$r]) = (@sq[$n-1-$c;$n-1-$r], @sq[$c;$r]); } } }
multi sub gen-sq ($n where {$n %% 2 and $n % 4}) { my $h = $n div 2; gen-sq($h); $i *= 4; for ^$h -> $r { for ^$h -> $c { @sq[$r + $h;$c] = @sq[$r;$c] + $h² * 3; @sq[$r;$c + $h] = @sq[$r;$c] + $h² * 2; @sq[$r + $h;$c + $h] = @sq[$r;$c] + $h²; } for ^(($h-1)/2) -> $c { next if $c == 0 and $r == ($h-1) div 2; (@sq[$r][$c], @sq[$r + $h][$c]) = (@sq[$r + $h][$c], @sq[$r][$c]); } } (@sq[($h-1)/2][($h-1)/2], @sq[($h-1)/2+$h][($h-1)/2]) = (@sq[($h-1)/2+$h][($h-1)/2], @sq[($h-1)/2][($h-1)/2]); if $h > 4 { for ^$h -> $r { for ($n - ($h-3) / 2) ..^ $n -> $c { (@sq[$r][$c], @sq[$r + $h][$c]) = (@sq[$r + $h][$c], @sq[$r][$c]); } } } }
}</lang>