Recently I have made the research for most-perfect magic squares 4x4.
You don't need to generate 16! permutations, most of them are not useful for your goal. You can use only 4! permutations of { 1, 2, 4, 8 }. Here is how:
| A | B | AT | BT |
0 1 1 0 1 0 0 1 0 1 1 0 1 0 0 1 | 0 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 | 0 1 0 1 1 0 1 0 1 0 1 0 0 1 0 1 | 0 1 0 1 0 1 0 1 1 0 1 0 1 0 1 0 |
- Use matrices { A, B, AT, BT } multiplied by values { 1, 2, 4, 8 } in any order;
- Add them (A*v0 + B*v1 + AT*v2 + BT*v3);
- Increase all values of the matrix by lowest value you want (sum +1).
If you will use all permutations of { 1, 2, 4, 8 } you will get all most-perfect magic squares 4x4 (in range [L..L+15]) with the lowest value in top left corner. Examples (3/24):
| v | A v[0] | B v[1] | AT v[2] | BT v[3] | S | S+1 |
1 2 4 8 | _ 1 1 1 1 1 1 1 1 | _ 2 2 2 2 2 2 2 2 | _ 4 4 4 4 4 4 4 4 | _ 8 8 8 8 8 8 8 8 | 0 13 3 14 7 10 4 9 12 1 15 2 11 6 8 5 | 1 14 4 15 8 11 5 10 13 2 16 3 12 7 9 6 |
1 4 2 8 | _ 1 1 1 1 1 1 1 1 | _ 4 4 4 4 4 4 4 4 | _ 2 2 2 2 2 2 2 2 | _ 8 8 8 8 8 8 8 8 | 0 11 5 14 7 12 2 9 10 1 15 4 13 6 8 3 | 1 12 6 15 8 13 3 10 11 2 16 5 14 7 9 4 |
2 4 1 8 | _ 2 2 2 2 2 2 2 2 | _ 4 4 4 4 4 4 4 4 | _ 1 1 1 1 1 1 1 1 | _ 8 8 8 8 8 8 8 8 | 0 11 6 13 7 12 1 10 9 2 15 4 14 5 8 3 | 1 12 7 14 8 13 2 11 10 3 16 5 15 6 9 4 |
To get magic squares with the lowest value in certain location you can shift matrices { A, B, AT, BT } to that location. Examples:
| v | A# v[0] | B# v[1] | AT# v[2] | BT# v[3] | S# | S#+1 |
2 4 8 1 | 2 2 2 2 2 _ 2 2 2 | 4 4 4 4 4 4 _ 4 4 | 8 8 8 8 8 _ 8 8 8 | 1 1 1 1 1 _ 1 1 1 | 15 4 9 2 1 10 7 12 6 13 0 11 8 3 14 5 | 16 5 10 3 2 11 8 13 7 14 1 12 9 4 15 6 |
4 8 1 2 | 4 4 4 4 4 _ 4 4 4 | 8 8 8 8 8 8 _ 8 8 | 1 1 1 1 1 _ 1 1 1 | 2 2 2 2 2 _ 2 2 2 | 15 8 3 4 2 5 14 9 12 11 0 7 1 6 13 10 | 16 9 4 5 3 6 15 10 13 12 1 8 2 7 14 11 |
8 2 4 1 | 8 8 8 8 8 _ 8 8 8 | 2 2 2 2 2 2 _ 2 2 | 4 4 4 4 4 _ 4 4 4 | 1 1 1 1 1 _ 1 1 1 | 15 2 5 8 1 12 11 6 10 7 0 13 4 9 14 3 | 16 3 6 9 2 13 12 7 11 8 1 14 5 10 15 4 |
Python 3:
def B_f(x, y): return x >> 1 & 1 ^ y & 1 def A_f(x, y): return B_f(x + 1, y) def AT_f(x, y): return A_f(y, x) def BT_f(x, y): return B_f(y, x) def magic_square_4x4_f(v, l, x0, y0, w = 4, h = 4): return [ [ + A_f(x - x0, y - y0) * v[0] + B_f(x - x0, y - y0) * v[1] + AT_f(x - x0, y - y0) * v[2] + BT_f(x - x0, y - y0) * v[3] + l for x in range(w) ] for y in range(h) ] from itertools import permutations def print_all_4x4(x0, y0): for v in permutations({ 1, 2, 4, 8 }): print(magic_square_4x4_f(v, +1, x0, y0)) # print_all_4x4(0, 0) # 24/384 for y in range(4): for x in range(4): print_all_4x4(x, y) # 24 * 4 * 4 = 384 magic squares
This code generates all magic squares 4x4 efficiently. Here is couple first and last lines of the output:
[[1, 15, 10, 8], [12, 6, 3, 13], [7, 9, 16, 2], [14, 4, 5, 11]] [[1, 15, 10, 8], [14, 4, 5, 11], [7, 9, 16, 2], [12, 6, 3, 13]] [[1, 14, 11, 8], [12, 7, 2, 13], [6, 9, 16, 3], [15, 4, 5, 10]] [[1, 14, 11, 8], [15, 4, 5, 10], [6, 9, 16, 3], [12, 7, 2, 13]] ... [[4, 9, 7, 14], [5, 16, 2, 11], [10, 3, 13, 8], [15, 6, 12, 1]] [[10, 3, 13, 8], [5, 16, 2, 11], [4, 9, 7, 14], [15, 6, 12, 1]] [[4, 9, 6, 15], [5, 16, 3, 10], [11, 2, 13, 8], [14, 7, 12, 1]] [[11, 2, 13, 8], [5, 16, 3, 10], [4, 9, 6, 15], [14, 7, 12, 1]]