魔方





5.00/5 (4投票s)
生成奇数和双偶数阶魔方的代码。
引言
在数学中,魔方是魔方的三维等价物,即,将一些整数排列在一个 n x n x n 的模式中,使得每一行、每一列、每一柱以及四个主空间对角线的数字之和等于一个单独的数字,即所谓的魔方常数。
术语
- 阶数 - n x n x n 魔方中 n 的值。
- 魔方常数 - 任何行、列、柱或对角线的唯一和。其值为 n(n3+1)/2。
奇数魔方的扩展暹罗法
暹罗法是一种构造奇数阶魔方的方法。这种方法可以扩展到三维来构造魔方。假设读者理解暹罗法。
我们可以使用索引表示法来表示任何魔方,例如 [1,2,3],它代表魔方的第 1 层、第 2 行和第 3 列。索引从 [0,0,0] 开始,索引的最大值为 [n-1,n-1,n-1]。
任何移动都会循环(就像吃豆人或黑客帝国中的列车隧道一样)。-1 值等同于 n-1,n 等同于 0。
我们从一个空的魔方开始。步骤
- 将数字 1 放置在顶层中间 [0,(n-1)/2,(n-1)/2]。
- 让我们将当前位置表示为 [l,r,c]。
- 移动到 [l-1,r,c-1]。
- 如果 [l-1,r,c-1] 已经被占用,则移动到 [l-1,r-1,c]。
- 如果 [l-1,r-1,c] 也被占用,则移动到 [l+1,r,c]。
- 用下一个数字填充当前单元格,并从第 2 步开始迭代,直到所有单元格都填充了从 1 到 n3 的数字。
双偶数魔方
创建魔方的逻辑可以从以下魔方扩展而来
1 | 15 | 14 | 4 |
12 | 6 | 7 | 9 |
8 | 10 | 11 | 5 |
13 | 3 | 2 | 16 |
上述魔方可以按照以下方式创建。
从左上角开始填充正方形。如果数字位于红色方框中,则填充该数字,否则用 17-数字(或 n2+1-数字)填充。
让我们将红色定义为奇偶校验 0,蓝色定义为奇偶校验 1。
计算魔方索引 [r,c] 奇偶校验的逻辑
int nBy4 = n / 4;
boolean parity = false;
if (r >= nBy4 && r < 3 * nBy4) {
parity = true;
}
if (c >= nBy4 && c < 3 * nBy4) {
parity = !parity;
}
类似地,可以构造一个魔方。
单偶数魔方
这里的逻辑变得有些复杂,因此超出了本文的范围。可以使用 Medjig 方法来构造这些魔方。在演示源代码中,我还包含生成任何阶魔方(包括单偶数魔方)的代码。相同的逻辑可以扩展到生成立方体。
代码
这段代码非常简单。
public static int[][][] getMagicCube(int n) {
if (n % 2 == 1) {
int[][][] magicCube = new int[n][n][n];
// layer index, row index, column index
int l, r, c;
l = 0;
r = n / 2;
c = n / 2;
// If you want to port this code in C++
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
for (int k = 0; k < magicCube.length; k++) {
magicCube[i][j][k] = 0;
}
}
}
int last = (int) Math.pow(n, 3);
for (int i = 0; i < last; i++) {
magicCube[l][r][c] = i + 1;
l--;
l = normalize(n, l);
c--;
c = normalize(n, c);
if (magicCube[l][r][c] != 0) {
r--;
r = normalize(n, r);
c++;
c = normalize(n, c);
if (magicCube[l][r][c] != 0) {
r++;
r = normalize(n, r);
l += 2;
l = normalize(n, l);
}
}
}
return magicCube;
} else if (n % 4 == 0) {
int[][][] magicCube = new int[n][n][n];
int lastPlusOne = (int) Math.pow(n, 3) + 1;
int number = 1;
int nBy4 = n / 4;
for (int l = 0; l < n; l++) {
for (int r = 0; r < n; r++) {
for (int c = 0; c < magicCube.length; c++) {
boolean parity = false;
if (l >= nBy4 && l < 3 * nBy4) {
parity = true;
}
if (r >= nBy4 && r < 3 * nBy4) {
parity = !parity;
}
if (c >= nBy4 && c < 3 * nBy4) {
parity = !parity;
}
magicCube[l][r][c] = (parity) ? lastPlusOne - number: number;
number++;
}
}
}
return magicCube;
}
throw new RuntimeException(
"Singly even magic cubes are not returned by this method.");
}
// index should be between 0 to n-1
private static int normalize(int n, int index) {
while (index < 0) {
index = index + n;
}
while (index > n - 1) {
index = index - n;
}
return index;
}
这个概念可以扩展到更高维度的立方体(超立方体)。您可以访问我的 网站,在那里您可以生成任何给定阶数和维度的魔方。
5 阶魔方的示例
由代码生成
第 1 层
109 | 77 | 75 | 43 | 11 |
97 | 70 | 38 | 6 | 104 |
65 | 33 | 1 | 124 | 92 |
28 | 21 | 119 | 87 | 60 |
16 | 114 | 82 | 55 | 48 |
第 2 层
15 | 108 | 76 | 74 | 42 |
103 | 96 | 69 | 37 | 10 |
91 | 64 | 32 | 5 | 123 |
59 | 27 | 25 | 118 | 86 |
47 | 20 | 113 | 81 | 54 |
第 3 层
41 | 14 | 107 | 80 | 73 |
9 | 102 | 100 | 68 | 36 |
122 | 95 | 63 | 31 | 4 |
90 | 58 | 26 | 24 | 117 |
53 | 46 | 19 | 112 | 85 |
第 4 层
72 | 45 | 13 | 106 | 79 |
40 | 8 | 101 | 99 | 67 |
3 | 121 | 94 | 62 | 35 |
116 | 89 | 57 | 30 | 23 |
84 | 52 | 50 | 18 | 111 |
第 5 层
78 | 71 | 44 | 12 | 110 |
66 | 39 | 7 | 105 | 98 |
34 | 2 | 125 | 93 | 61 |
22 | 120 | 88 | 56 | 29 |
115 | 83 | 51 | 49 | 17 |