Magic Square of Singly Even Order
Problem
Given an even integer n where n % 4 == 2 (i.e. n = 4k + 2), construct a normal magic square of order n containing the integers 1..n^2 exactly once so that every row, every column and the two main diagonals sum to the magic constant M = n*(n^2+1)/2.
Singly-even orders (6, 10, 14, ...) are traditionally constructed by splitting the grid into four (n/2 x n/2) odd-order magic subsquares and then swapping columns and a few cells. The Strachey (4-subsquare / composite) method below is simple to implement and widely used.
Examples
Example 1
Input: n = 6
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
Explanation: One valid output
Solution
Method 1 - 4-subsquare method
Intuition
-
Let
nbe the order wheren % 4 == 2and setm = n/2(somis odd). Build fourm x modd-order magic squares using the Siamese method and place them as four quadrants:|
A|C| |D|B| -
Use offsets so the four subsquares cover consecutive blocks of numbers:
A:1 .. m^2B:m^2+1 .. 2*m^2C:2*m^2+1 .. 3*m^2D:3*m^2+1 .. 4*m^2(which equalsn^2)
-
Compute
k = (n - 2) / 4. The high-level swaps are:- Swap the leftmost
kcolumns ofAwith the corresponding columns ofD. - Swap the rightmost
k-1columns ofCwith the corresponding columns ofB. - Swap two special central cells between
AandD: the middle cell in the leftmost column and the central cell of the subsquare. These correct the center coupling between quadrants.
- Swap the leftmost
The procedure yields a valid magic square for every n = 4k + 2.
Approach
-
Build four
m x modd-order magic squares using the Siamese method and place them as quadrants:|
A|C| |D|B| -
Use offsets so the quadrants cover consecutive ranges:
A=1..m^2,B=m^2+1..2*m^2,C=2*m^2+1..3*m^2,D=3*m^2+1..4*m^2. -
Perform these operations in sequence:
- Swap the leftmost
k = (n-2)/4columns betweenAandD. - Swap the rightmost
k-1columns betweenCandB. - Swap two special central cells between
AandD(usemid = m/2).
- Swap the leftmost
These steps preserve the row/column sums and yield a normal magic square of order n = 4k + 2.
Pseudocode
function generate(n):
if n is odd: return siamese(n)
if n % 4 == 0: return generate_doubly_even(n)
m = n/2
base = siamese(m) # m x m odd magic square
ans = zero matrix n x n
# place subsquares with offsets (use m2 = m*m)
for i in 0..m-1:
for j in 0..m-1:
ans[i][j] = base[i][j] + 0 # A
ans[i][j + m] = base[i][j] + 2*m*m # C
ans[i + m][j] = base[i][j] + 3*m*m # D
ans[i + m][j+m] = base[i][j] + 1*m*m # B
k = (n - 2) / 4
swap leftmost k columns between A and D
swap rightmost (k-1) columns between C and B
mid = m/2
swap two special cells between A and D using mid
return ans
Notes:
-
k = (n - 2) / 4controls the number of full-column swaps. -
mid = m/2is used when swapping the two special central cells.
Dry run
Here n = 6, m = 3, m^2 = 9, k = (6-2)/4 = 1. We use the standard 3×3 Lo-Shu (Siamese) pattern for each subsquare and add offsets of 0, 9, 18, 27 respectively.
Lo-Shu (base m = 3):
8 1 6
3 5 7
4 9 2
Make the subsquares by adding offsets:
A (1..9) = base + 0
B (10..18)= base + 9
C (19..27)= base + 18
D (28..36)= base + 27
Place them as quadrants A | C over D | B to compose the 6×6 before swaps:
8 1 6 | 26 19 24
3 5 7 | 21 23 25
4 9 2 | 22 27 20
---------+--------
35 28 33 | 17 10 15
30 32 34 | 12 14 16
31 36 29 | 13 18 11
Step 1 — swap leftmost k = 1 column of A and D (column index 0):
Before swap (A and D shown):
A:
8 1 6
3 5 7
4 9 2
D:
26 19 24
21 23 25
22 27 20
After swapping column 0 of A with column 0 of D:
A becomes:
35 1 6
30 5 7
31 9 2
D becomes:
8 28 33
3 32 34
4 36 29
Step 2 — swap the two special central cells between A and D (using mid = 1):
Swap A[mid][0] <-> D[mid][0] and A[mid][mid] <-> D[mid][mid].
Final 6×6 after all swaps:
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
This matches the classical 6×6 Strachey example and every row, column and main diagonal sums to 111.
Code
The implementations below present a canonical instance method generate(n) on a Solution type. The Java version preserves inline comments.
C++
using namespace std;
class Solution {
public:
vector<vector<int>> generate(int n) {
if (n % 2 == 1) return generateOdd(n);
if (n % 4 == 0) return generateDoublyEven(n);
int m = n / 2;
int m2 = m * m;
// build base m x m odd magic square (Siamese method)
auto base = siamese(m);
vector<vector<int>> ans(n, vector<int>(n));
// offsets: A:0, B:m2, C:2*m2, D:3*m2
for (int i = 0; i < m; ++i)
for (int j = 0; j < m; ++j) {
ans[i][j] = base[i][j] + 0; // A
ans[i][j + m] = base[i][j] + 2 * m2; // C
ans[i + m][j] = base[i][j] + 3 * m2; // D
ans[i + m][j + m] = base[i][j] + m2; // B
}
int k = (n - 2) / 4;
// swap leftmost k columns of A and D
for (int col = 0; col < k; ++col)
for (int row = 0; row < m; ++row)
swap(ans[row][col], ans[row + m][col]);
// swap rightmost (k-1) columns of C and B
for (int col = m - (k - 1); col < m; ++col)
for (int row = 0; row < m; ++row)
swap(ans[row][col + m], ans[row + m][col + m]);
// final special swaps (middle of leftmost column and central cell)
int mid = m / 2;
swap(ans[mid][0], ans[mid + m][0]);
swap(ans[mid][mid], ans[mid + m][mid]);
return ans;
}
private:
vector<vector<int>> siamese(int m) {
vector<vector<int>> a(m, vector<int>(m, 0));
int num = 1;
int i = 0, j = m / 2;
while (num <= m * m) {
a[i][j] = num++;
int ni = (i - 1 + m) % m;
int nj = (j + 1) % m;
if (a[ni][nj]) i = (i + 1) % m;
else { i = ni; j = nj; }
}
return a;
}
// Minimal helpers for parity cases; straightforward implementations.
vector<vector<int>> generateOdd(int n) { return siamese(n); }
vector<vector<int>> generateDoublyEven(int n) {
vector<vector<int>> ans(n, vector<int>(n));
int cnt = 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
ans[i][j] = cnt++;
int total = n * n + 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) {
int r = i % 4, c = j % 4;
if (r == c || r + c == 3) ans[i][j] = total - ans[i][j];
}
return ans;
}
};
Java
class Solution {
public int[][] generate(int n) {
if (n % 2 == 1) return generateOdd(n);
if (n % 4 == 0) return generateDoublyEven(n);
int m = n / 2;
int m2 = m * m;
int[][] base = siamese(m);
int[][] ans = new int[n][n];
// place A, C, D, B with offsets 0, 2*m2, 3*m2, m2 respectively
for (int i = 0; i < m; ++i) {
for (int j = 0; j < m; ++j) {
ans[i][j] = base[i][j]; // A
ans[i][j + m] = base[i][j] + 2 * m2; // C
ans[i + m][j] = base[i][j] + 3 * m2; // D
ans[i + m][j + m] = base[i][j] + m2; // B
}
}
int k = (n - 2) / 4;
// swap leftmost k columns of A and D
for (int col = 0; col < k; ++col)
for (int row = 0; row < m; ++row)
swap(ans, row, col, row + m, col);
// swap rightmost (k-1) columns of C and B
for (int col = m - (k - 1); col < m; ++col)
for (int row = 0; row < m; ++row)
swap(ans, row, col + m, row + m, col + m);
int mid = m / 2;
swap(ans, mid, 0, mid + m, 0);
swap(ans, mid, mid, mid + m, mid);
return ans;
}
private void swap(int[][] a, int r1, int c1, int r2, int c2) {
int t = a[r1][c1]; a[r1][c1] = a[r2][c2]; a[r2][c2] = t;
}
private int[][] siamese(int m) {
int[][] a = new int[m][m];
int num = 1;
int i = 0, j = m / 2;
while (num <= m * m) {
a[i][j] = num++;
int ni = (i - 1 + m) % m;
int nj = (j + 1) % m;
if (a[ni][nj] != 0) i = (i + 1) % m;
else { i = ni; j = nj; }
}
return a;
}
private int[][] generateOdd(int n) { return siamese(n); }
private int[][] generateDoublyEven(int n) {
int[][] ans = new int[n][n];
int cnt = 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
ans[i][j] = cnt++;
int total = n * n + 1;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) {
int r = i % 4, c = j % 4;
if (r == c || r + c == 3) ans[i][j] = total - ans[i][j];
}
return ans;
}
}
Python
class Solution:
def generate(self, n: int) -> list[list[int]]:
if n % 2 == 1:
return self.siamese(n)
if n % 4 == 0:
return self.generate_doubly_even(n)
m = n // 2
m2 = m * m
base = self.siamese(m)
ans = [[0] * n for _ in range(n)]
# place A, C, D, B with offsets 0, 2*m2, 3*m2, m2
for i in range(m):
for j in range(m):
ans[i][j] = base[i][j]
ans[i][j + m] = base[i][j] + 2 * m2
ans[i + m][j] = base[i][j] + 3 * m2
ans[i + m][j + m] = base[i][j] + m2
k = (n - 2) // 4
# swap leftmost k columns of A and D
for col in range(k):
for row in range(m):
ans[row][col], ans[row + m][col] = ans[row + m][col], ans[row][col]
# swap rightmost (k-1) columns of C and B
for col in range(m - (k - 1), m):
for row in range(m):
ans[row][col + m], ans[row + m][col + m] = ans[row + m][col + m], ans[row][col + m]
mid = m // 2
ans[mid][0], ans[mid + m][0] = ans[mid + m][0], ans[mid][0]
ans[mid][mid], ans[mid + m][mid] = ans[mid + m][mid], ans[mid][mid]
return ans
def siamese(self, m: int) -> list[list[int]]:
a = [[0] * m for _ in range(m)]
num = 1
i, j = 0, m // 2
while num <= m * m:
a[i][j] = num
num += 1
ni, nj = (i - 1) % m, (j + 1) % m
if a[ni][nj]:
i = (i + 1) % m
else:
i, j = ni, nj
return a
def generate_doubly_even(self, n: int) -> list[list[int]]:
ans = [[0] * n for _ in range(n)]
cnt = 1
for i in range(n):
for j in range(n):
ans[i][j] = cnt
cnt += 1
total = n * n + 1
for i in range(n):
for j in range(n):
r, c = i % 4, j % 4
if r == c or r + c == 3:
ans[i][j] = total - ans[i][j]
return ans
Complexity
- ⏰ Time complexity:
O(n^2)— building the subsquares and performing swaps visitsO(n^2) - 🧺 Space complexity:
O(n^2)for the output matrix.