Magic squares/Raku: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Perl 6}}: Style tweaks)
m (syntax highlighting)
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
Rather than having multiple examples for different orders of magic square, this will generate a magic square for ''any'' valid n x n grid.
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.
Invoke at the command line and pass in the desired size as a parameter.


Line 5: Line 6:


See:<ul>
See:<ul>
<li>[[Magic_squares_of_odd_order#Perl_6|Magic squares of odd order#Perl 6]]</li>
<li>[[Magic_squares_of_odd_order#Raku|Magic squares of odd order#Raku]]</li>
<li>[[Magic_squares_of_singly_even_order#Perl_6|Magic squares of singly even order#Perl 6]]</li>
<li>[[Magic_squares_of_singly_even_order#Raku|Magic squares of singly even order#Raku]]</li>
<li>[[Magic_squares_of_doubly_even_order#Perl_6|Magic squares of doubly even order#Perl 6]]</li>
<li>[[Magic_squares_of_doubly_even_order#Raku|Magic squares of doubly even order#Raku]]</li>
</ul>
</ul>


<lang perl6>sub MAIN (Int $n where {$n > 0}) {
<syntaxhighlight lang="raku" line>sub MAIN (Int $n where {$n > 0}) {


my @sq;
my @sq;
my $i = 1;
my $i = 1;
my $h = $n div 2;
my $q = $n div 4;
gen-sq($n);
gen-sq($n);


Line 21: Line 25:




multi sub gen-sq (2) {
multi sub gen-sq (2) { # invalid
note "Sorry, can not generate a 2 x 2 magic square." and exit;
note "Sorry, can not generate a 2 x 2 magic square." and exit;
}
}


multi sub gen-sq ($n where {$n % 2}) {
multi sub gen-sq ($n where {$n % 2}) { # odd
my $x = $n/2;
my $x = $n/2;
my $y = 0;
my $y = 0;
Line 31: Line 35:
}
}


multi sub gen-sq ($n where {$n %% 4}) {
multi sub gen-sq ($n where {$n %% 4}) { # doubly even
my $x = 0;
my $x = 0;
my $y = 0;
my $y = 0;
@sq[$i % $n ?? $y !! $y++][($i-1) % $n] = $i++ for ^$n²;
@sq[$i % $n ?? $y !! $y++][($i-1) % $n] = $i++ for ^$n²;
my $t;
for ^$q -> $r {
for 0 ..^ $n div 4 -> $r {
for $q ..^ $n - $q -> $c {
for $n div 4 ..^ $n - $n div 4 -> $c {
my $ŕ = $n - 1 - $r;
(@sq[$r;$c], @sq[$n-1-$r;$n-1-$c]) =
my $ć = $n - 1 - $c;
(@sq[$n-1-$r;$n-1-$c], @sq[$r;$c]);
(@sq[$r;$c], @sq[$ŕ;$ć]) = (@sq[$ŕ;$ć], @sq[$r;$c]);
(@sq[$c;$r], @sq[$n-1-$c;$n-1-$r]) =
(@sq[$c;$r], @sq[$ć;$ŕ]) = (@sq[$ć;$ŕ], @sq[$c;$r]);
(@sq[$n-1-$c;$n-1-$r], @sq[$c;$r]);
}
}
}
}
}
}


multi sub gen-sq ($n where {$n %% 2 and $n % 4}) {
multi sub gen-sq ($n where {$n %% 2 and $n % 4}) { # singly even
my $h = $n div 2;
gen-sq($h);
gen-sq($h);
$i *= 4;
$i *= 4;
for ^$h -> $r {
for ^$h -> $r {
for ^$h -> $c {
for ^$h -> $c {
@sq[$r + $h;$c] = @sq[$r;$c] + $h² * 3;
@sq[$r + $h; $c] = @sq[$r;$c] + $h² * 3;
@sq[$r;$c + $h] = @sq[$r;$c] + $h² * 2;
@sq[$r; $c + $h] = @sq[$r;$c] + $h² * 2;
@sq[$r + $h;$c + $h] = @sq[$r;$c] + $h²;
@sq[$r + $h; $c + $h] = @sq[$r;$c] + $h²;
}
}
for ^(($h-1)/2) -> $c {
for ^$q -> $c {
next if $c == 0 and $r == ($h-1) div 2;
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[$r;$c], @sq[$r + $h;$c]) = (@sq[$r + $h;$c], @sq[$r;$c]);
}
}
}
if $h > 4 {
(@sq[($h-1)/2][($h-1)/2], @sq[($h-1)/2+$h][($h-1)/2]) =
for ($n - $q + 1) ..^ $n -> $c {
(@sq[($h-1)/2+$h][($h-1)/2], @sq[($h-1)/2][($h-1)/2]);
(@sq[$r;$c], @sq[$r + $h;$c]) = (@sq[$r + $h;$c], @sq[$r;$c]);
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]);
}
}
}
}
}
}
(@sq[$q;$q], @sq[$q+$h;$q]) = (@sq[$q+$h;$q], @sq[$q;$q]);
}
}
}</lang>
}</syntaxhighlight>

Latest revision as of 21:58, 28 August 2022

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.

Works with: Rakudo version 2016-02

See:

sub MAIN (Int $n where {$n > 0}) {

    my @sq;
    my $i = 1;
    my $h = $n div 2;
    my $q = $n div 4;
    
    gen-sq($n);

    say .fmt("%{$i.chars}d", ' ') for @sq;

    say "\nThe magic number is ", [+] @sq[0].list;


    multi sub gen-sq (2) { # invalid
        note "Sorry, can not generate a 2 x 2 magic square." and exit;
    }

    multi sub gen-sq ($n where {$n % 2}) { # odd
        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}) { # doubly even
        my $x = 0;
        my $y = 0;
        @sq[$i % $n ?? $y !! $y++][($i-1) % $n] = $i++ for ^$n²;
        for ^$q -> $r {
            for $q ..^ $n - $q -> $c {
                my  = $n - 1 - $r;
                my  = $n - 1 - $c;
                (@sq[$r;$c], @sq[;]) = (@sq[;], @sq[$r;$c]);
                (@sq[$c;$r], @sq[;]) = (@sq[;], @sq[$c;$r]);
            }
        }
    }

    multi sub gen-sq ($n where {$n %% 2 and $n % 4}) { # singly even
        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 ^$q -> $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]);
            }
            if $h > 4 {
                for ($n - $q + 1) ..^ $n -> $c {
                        (@sq[$r;$c], @sq[$r + $h;$c]) = (@sq[$r + $h;$c], @sq[$r;$c]);
                }
            }
        }
        (@sq[$q;$q], @sq[$q+$h;$q]) = (@sq[$q+$h;$q], @sq[$q;$q]);
    }
}