Magic squares of singly even order

From Rosetta Code
Revision as of 22:03, 17 March 2016 by Thundergnat (talk | contribs) (→‎{{header|Perl 6}}: Replace accidentally removed header)
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

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