Magic squares of singly even order: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Perl 6}}: Replace accidentally removed header)
(added FreeBASIC)
Line 12: Line 12:
* [http://www.1728.org/magicsq3.htm Singly Even Magic Squares (1728.org)]<br><br>
* [http://www.1728.org/magicsq3.htm Singly Even Magic Squares (1728.org)]<br><br>


=={{header|FreeBASIC}}==
<lang freebasic>' version 18-03-2016
' compile with: fbc -s console
' singly even magic square 6, 10, 14, 18...

Sub Err_msg(msg As String)
Print msg
Beep : Sleep 5000, 1 : Exit Sub
End Sub

Sub se_magicsq(n As UInteger, filename As String = "")

' filename <> "" then save square in a file
' filename can contain directory name
' if filename exist it will be overwriten, no error checking

If n < 6 Then
Err_msg( "Error: n is to small")
Exit Sub
End If

If ((n -2) Mod 4) <> 0 Then
Err_msg "Error: not possible to make singly" + _
" even magic square size " + Str(n)
Exit Sub
End If

Dim As UInteger sq(1 To n, 1 To n)
Dim As UInteger magic_sum = n * (n ^ 2 +1) \ 2
Dim As UInteger sq_d_2 = n \ 2, q2 = sq_d_2 ^ 2
Dim As UInteger l = (n -2) \ 4
Dim As UInteger x = sq_d_2 \ 2 + 1, y = 1, nr = 1
Dim As String frmt = String(Len(Str(n * n)) +1, "#")

' fill pattern A C
' D B
' main loop for creating magic square in section A
' the value for B,C and D is derived from A
' uses the FreeBASIC odd order magic square routine
Do
If sq(x, y) = 0 Then
sq(x , y ) = nr ' A
sq(x + sq_d_2, y + sq_d_2) = nr + q2 ' B
sq(x + sq_d_2, y ) = nr + q2 * 2 ' C
sq(x , y + sq_d_2) = nr + q2 * 3 ' D
If nr Mod sq_d_2 = 0 Then
y += 1
Else
x += 1 : y -= 1
End If
nr += 1
End If
If x > sq_d_2 Then
x = 1
Do While sq(x,y) <> 0
x += 1
Loop
End If
If y < 1 Then
y = sq_d_2
Do While sq(x,y) <> 0
y -= 1
Loop
End If
Loop Until nr > q2


' swap left side
For y = 1 To sq_d_2
For x = 1 To l
Swap sq(x, y), sq(x,y + sq_d_2)
Next
Next
' make indent
y = (sq_d_2 \ 2) +1
Swap sq(1, y), sq(1, y + sq_d_2) ' was swapped, restore to orignal value
Swap sq(l +1, y), sq(l +1, y + sq_d_2)

' swap right side
For y = 1 To sq_d_2
For x = n - l +2 To n
Swap sq(x, y), sq(x,y + sq_d_2)
Next
Next

' check columms and rows
For y = 1 To n
nr = 0 : l = 0
For x = 1 To n
nr += sq(x,y)
l += sq(y,x)
Next
If nr <> magic_sum Or l <> magic_sum Then
Err_msg "Error: value <> magic_sum"
Exit Sub
End If
Next

' check diagonals
nr = 0 : l = 0
For x = 1 To n
nr += sq(x, x)
l += sq(n - x +1, n - x +1)
Next
If nr <> magic_sum Or l <> magic_sum Then
Err_msg "Error: value <> magic_sum"
Exit Sub
End If
' printing square's on screen bigger when
' n > 19 results in a wrapping of the line
Print "Single even magic square size: "; n; "*"; n
Print "The magic sum = "; magic_sum
Print
For y = 1 To n
For x = 1 To n
Print Using frmt; sq(x, y);
Next
Print
Next

' output magic square to a file with the name provided
If filename <> "" Then
nr = FreeFile
Open filename For Output As #nr
Print #nr, "Single even magic square size: "; n; "*"; n
Print #nr, "The magic sum = "; magic_sum
Print #nr,
For y = 1 To n
For x = 1 To n
Print #nr, Using frmt; sq(x,y);
Next
Print #nr,
Next
Close #nr
End If

End Sub

' ------=< MAIN >=------

se_magicsq(6, "magicse6.txt") : Print

' empty keyboard buffer
While Inkey <> "" : Var _key_ = Inkey : Wend
Print : Print "hit any key to end program"
Sleep
End</lang>
{{out}}
<pre>Single even magic square size: 6*6
The magic sum = 111

35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11</pre>
=={{header|Java}}==
=={{header|Java}}==
<lang java>public class MagicSquareSinglyEven {
<lang java>public class MagicSquareSinglyEven {

Revision as of 15:39, 18 March 2016

Magic squares of singly even order is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

A magic square of singly even order has a size that is a multiple of 4, plus 2 (e.g. 6, 10, 14). This means that the subsquares have an odd size, which plays a role in the construction.

The task: create a magic square of 6 x 6.

Cf.
See also

FreeBASIC

<lang freebasic>' version 18-03-2016 ' compile with: fbc -s console ' singly even magic square 6, 10, 14, 18...

Sub Err_msg(msg As String)

   Print msg
   Beep : Sleep 5000, 1 : Exit Sub

End Sub

Sub se_magicsq(n As UInteger, filename As String = "")

   ' filename <> "" then save square in a file
   ' filename can contain directory name
   ' if filename exist it will be overwriten, no error checking
   If n < 6 Then
       Err_msg( "Error: n is to small")
       Exit Sub
   End If
   If ((n -2) Mod 4) <> 0 Then
       Err_msg "Error: not possible to make singly" + _
                " even magic square size " + Str(n)
       Exit Sub
   End If
   Dim As UInteger sq(1 To n, 1 To n)
   Dim As UInteger magic_sum = n * (n ^ 2 +1) \ 2
   Dim As UInteger sq_d_2 = n \ 2, q2 = sq_d_2 ^ 2
   Dim As UInteger l = (n -2) \ 4
   Dim As UInteger x = sq_d_2 \ 2 + 1, y = 1, nr = 1
   Dim As String frmt = String(Len(Str(n * n)) +1, "#")
   ' fill pattern A C
   '              D B
   ' main loop for creating magic square in section A
   ' the value for B,C and D is derived from A
   ' uses the FreeBASIC odd order magic square routine
   Do
       If sq(x, y) = 0 Then
           sq(x         , y         ) = nr          ' A
           sq(x + sq_d_2, y + sq_d_2) = nr + q2     ' B
           sq(x + sq_d_2, y         ) = nr + q2 * 2 ' C
           sq(x         , y + sq_d_2) = nr + q2 * 3 ' D
           If nr Mod sq_d_2 = 0 Then
               y += 1
           Else
               x += 1 : y -= 1
           End If
           nr += 1
       End If
       If x > sq_d_2 Then
           x = 1
           Do While sq(x,y) <> 0
               x += 1
           Loop
       End If
       If y < 1 Then
           y = sq_d_2
           Do While sq(x,y) <> 0
               y -= 1
           Loop
       End If
   Loop Until nr > q2


   ' swap left side
   For y = 1 To sq_d_2
       For x = 1 To l
           Swap sq(x, y), sq(x,y + sq_d_2)
       Next
   Next
   ' make indent
   y = (sq_d_2 \ 2) +1
   Swap sq(1, y), sq(1, y + sq_d_2) ' was swapped, restore to orignal value
   Swap sq(l +1, y), sq(l +1, y + sq_d_2)
   ' swap right side
   For y = 1 To sq_d_2
       For x = n - l +2 To n
           Swap sq(x, y), sq(x,y + sq_d_2)
       Next
   Next
   ' check columms and rows
   For y = 1 To n
       nr = 0 : l  = 0
       For x = 1 To n
           nr += sq(x,y)
           l  += sq(y,x)
       Next
       If nr <> magic_sum Or l <> magic_sum Then
           Err_msg "Error: value <> magic_sum"
           Exit Sub
       End If
   Next
   ' check diagonals
   nr = 0 : l = 0
   For x = 1 To n
       nr += sq(x, x)
       l  += sq(n - x +1, n - x +1)
   Next
   If nr <> magic_sum Or l <> magic_sum Then
       Err_msg "Error: value <> magic_sum"
       Exit Sub
   End If
   
   ' printing square's on screen bigger when
   ' n > 19 results in a wrapping of the line
   Print "Single even magic square size: "; n; "*"; n
   Print "The magic sum = "; magic_sum
   Print
   For y = 1 To n
       For x = 1 To n
           Print Using frmt; sq(x, y);
       Next
       Print
   Next
   ' output magic square to a file with the name provided
   If filename <> "" Then
       nr = FreeFile
       Open filename For Output As #nr
       Print #nr, "Single even magic square size: "; n; "*"; n
       Print #nr, "The magic sum = "; magic_sum
       Print #nr,
       For y = 1 To n
           For x = 1 To n
               Print #nr, Using frmt; sq(x,y);
           Next
           Print #nr,
       Next
       Close #nr
   End If

End Sub

' ------=< MAIN >=------

se_magicsq(6, "magicse6.txt") : Print

' empty keyboard buffer While Inkey <> "" : Var _key_ = Inkey : Wend Print : Print "hit any key to end program" Sleep End</lang>

Output:
Single even magic square size: 6*6
The magic sum = 111

 35  1  6 26 19 24
  3 32  7 21 23 25
 31  9  2 22 27 20
  8 28 33 17 10 15
 30  5 34 12 14 16
  4 36 29 13 18 11

Java

<lang java>public class MagicSquareSinglyEven {

   public static void main(String[] args) {
       int n = 6;
       for (int[] row : magicSquareSinglyEven(n)) {
           for (int x : row)
               System.out.printf("%2s ", x);
           System.out.println();
       }
       System.out.printf("\nMagic constant: %d ", (n * n + 1) * n / 2);
   }
   public static int[][] magicSquareOdd(final int n) {
       if (n < 3 || n % 2 == 0)
           throw new IllegalArgumentException("base must be odd and > 2");
       int value = 0;
       int gridSize = n * n;
       int c = n / 2, r = 0;
       int[][] result = new int[n][n];
       while (++value <= gridSize) {
           result[r][c] = value;
           if (r == 0) {
               if (c == n - 1) {
                   r++;
               } else {
                   r = n - 1;
                   c++;
               }
           } else if (c == n - 1) {
               r--;
               c = 0;
           } else if (result[r - 1][c + 1] == 0) {
               r--;
               c++;
           } else {
               r++;
           }
       }
       return result;
   }
   static int[][] magicSquareSinglyEven(final int n) {
       if (n < 6 || (n - 2) % 4 != 0)
           throw new IllegalArgumentException("base must be a positive "
                   + "multiple of 4 plus 2");
       int size = n * n;
       int halfN = n / 2;
       int subSquareSize = size / 4;
       int[][] subSquare = magicSquareOdd(halfN);
       int[] quadrantFactors = {0, 2, 3, 1};
       int[][] result = new int[n][n];
       for (int r = 0; r < n; r++) {
           for (int c = 0; c < n; c++) {
               int quadrant = (r / halfN) * 2 + (c / halfN);
               result[r][c] = subSquare[r % halfN][c % halfN];
               result[r][c] += quadrantFactors[quadrant] * subSquareSize;
           }
       }
       int nColsLeft = halfN / 2;
       int nColsRight = nColsLeft - 1;
       for (int r = 0; r < halfN; r++)
           for (int c = 0; c < n; c++) {
               if (c < nColsLeft || c >= n - nColsRight
                       || (c == nColsLeft && r == nColsLeft)) {
                   if (c == 0 && r == nColsLeft)
                       continue;
                   int tmp = result[r][c];
                   result[r][c] = result[r + halfN][c];
                   result[r + halfN][c] = tmp;
               }
           }
       return result;
   }

}</lang>

35  1  6 26 19 24 
 3 32  7 21 23 25 
31  9  2 22 27 20 
 8 28 33 17 10 15 
30  5 34 12 14 16 
 4 36 29 13 18 11 

Magic constant: 111

Perl 6

See Magic squares/Perl 6 for a general magic square generator. Note that it produces a magic square, not the magic square. The output is different each time.

Output:

With a parameter of 6:

26 35  1 19  6 24
17  8 28 10 33 15
12 30  5 14 34 16
13  4 36 18 29 11
21  3 32 23  7 25
22 31  9 27  2 20

The magic number is 111

With a parameter of 10:

 78  46  37  44  53  94  96  35  12  10
 97  45  31  38  72  13  95  29   6  79
 22  70  56  63  47  88  20  54  81   4
 90  33  49  26  65  76  83  42  24  17
 84  27  43  50  59 100  77  36  18  11
  9  52  68  75  34  25   2  61  93  86
 91  39  30  32  66  82  89  48   5  23
 16  64  55  57  41   7  14  73  80  98
 15  58  74  51  40   1   8  67  99  92
  3  71  62  69  28  19  21  60  87  85

The magic number is 505

zkl

Translation of: Java

<lang zkl>class MagicSquareSinglyEven{

  fcn init(n){ var result=magicSquareSinglyEven(n) }
  fcn toString{
     sink,n:=Sink(String),result.len();  // num collumns
     fmt:="%2s ";
     foreach row in (result)
        { sink.write(row.apply('wrap(n){ fmt.fmt(n) }).concat(),"\n") }
     sink.write("\nMagic constant: %d".fmt((n*n + 1)*n/2));
     sink.close();
  }
  fcn magicSquareOdd(n){
     if (n<3 or n%2==0) throw(Exception.ValueError("base must be odd and > 2"));
     value,gridSize,c,r:=0, n*n, n/2, 0;
     result:=n.pump(List(),n.pump(List(),0).copy);  // array[n,n] of zero

     while((value+=1)<=gridSize){

result[r][c]=value; if(r==0){ if(c==n-1) r+=1;

           else{ r=n-1; c+=1; }

} else if(c==n-1){ r-=1; c=0; } else if(result[r-1][c+1]==0){ r-=1; c+=1; } else r+=1;

     }
     result;
  }
  fcn magicSquareSinglyEven(n){
     if (n<6 or (n-2)%4!=0)

throw(Exception.ValueError("base must be a positive multiple of 4 +2"));

     size,halfN,subSquareSize:=n*n,  n/2, size/4;
     subSquare:=magicSquareOdd(halfN);
     quadrantFactors:=T(0, 2, 3, 1);
     result:=n.pump(List(),n.pump(List(),0).copy);  // array[n,n] of zero
     foreach r,c in (n,n){
        quadrant:=(r/halfN)*2 + (c/halfN);

result[r][c]=subSquare[r%halfN][c%halfN]; result[r][c]+=quadrantFactors[quadrant]*subSquareSize;

     }
     nColsLeft,nColsRight:=halfN/2, nColsLeft-1;
     foreach r,c in (halfN,n){
        if ( c<nColsLeft or c>=(n-nColsRight) or 
             (c==nColsLeft and r==nColsLeft) ){

if(c==0 and r==nColsLeft) continue; tmp:=result[r][c]; result[r][c]=result[r+halfN][c]; result[r+halfN][c]=tmp; }

     }
     result
  }   

}</lang> <lang zkl>MagicSquareSinglyEven(6).println();</lang>

Output:
35  1  6 26 19 24 
 3 32  7 21 23 25 
31  9  2 22 27 20 
 8 28 33 17 10 15 
30  5 34 12 14 16 
 4 36 29 13 18 11 

Magic constant: 111