如何通过旋转而不重复方向来计算立方体的所有方向?
How to compute all orientations of a cube by rotating, without repeating orientations?
我正在开发一个应用程序,以找出给定特定起始结构的拼图立方体的可能解决方案的数量。
我已将所有唯一解存储在内存中,我将与给定结构进行比较以确定可能的解数。
为此,我必须将立方体围绕每个面旋转 90 度 4 次,以便检查所有可能的方向。以后再考虑考虑。
对于一个立方体,有 6 个面和 4 个旋转,总共需要 24 次操作。
由于绕一个轴的旋转等同于绕另一个 2 轴的旋转这一事实,我正在努力实现一种有效的算法'。
例如:绕 x 轴旋转产生的方向与先绕 y 轴旋转然后再绕 z 轴旋转的方向相同。因此,我当前的实现需要 64 次操作,这是多余的,因为我多次检查相同的方向。
Image of application
当前算法:
public static int getPossibleSolutionCount(Map<PieceIndex, Piece> pieces)
{
int count = 0;
for (Solution s : solutions)
{
for (int z = 0; z < 4; z++)
{
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
if (s.isDerrivedFrom(pieces))
{
count++;
}
//all rotation calls rotate the piece / structure byt 90 degrees
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Y_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.X_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Z_AXIS));
}
}
return count;
}
我怎样才能改进这一点,这样我就不会重复相同的方向,即我只能签入 24 次迭代而不是 64 次。
24 次旋转中的每一次旋转都可以通过哪个面朝上(6 种可能性)和哪些面朝左(每个朝上的面有 4 种可能性)来唯一标识。
先用外循环确定朝上的面,再用内循环确定朝左的面似乎很容易。考虑到您的 rotate 调用需要的参数,我可能会这样做:
// Rotating around these axes in sequence will bring each face in turn
// to the top
private static GameObject.AXIS ROTATION_PATH = new GameObject.AXIS[] {
GameObject.AXIS.X_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.Z_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.Z_AXIS
};
public static int getPossibleSolutionCount(Map<PieceIndex, Piece> pieces)
{
int count = 0;
for (GameObject.AXIS path_axis: ROTATION_PATH)
{
for (int y = 0; y < 4; y++)
{
for (Solution s : solutions)
{
if (s.isDerivedFrom(pieces))
{
count++;
}
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Y_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(path_axis));
}
return count;
}
希望您了解它的工作原理。我假设了你的轴指向哪个方向以及事物旋转的方向,所以如果 ROTATION_PATH 没有为你做它应该做的事情,然后相应地调整它。
我正在开发一个应用程序,以找出给定特定起始结构的拼图立方体的可能解决方案的数量。
我已将所有唯一解存储在内存中,我将与给定结构进行比较以确定可能的解数。
为此,我必须将立方体围绕每个面旋转 90 度 4 次,以便检查所有可能的方向。以后再考虑考虑。
对于一个立方体,有 6 个面和 4 个旋转,总共需要 24 次操作。
由于绕一个轴的旋转等同于绕另一个 2 轴的旋转这一事实,我正在努力实现一种有效的算法'。
例如:绕 x 轴旋转产生的方向与先绕 y 轴旋转然后再绕 z 轴旋转的方向相同。因此,我当前的实现需要 64 次操作,这是多余的,因为我多次检查相同的方向。
Image of application
当前算法:
public static int getPossibleSolutionCount(Map<PieceIndex, Piece> pieces)
{
int count = 0;
for (Solution s : solutions)
{
for (int z = 0; z < 4; z++)
{
for (int x = 0; x < 4; x++)
{
for (int y = 0; y < 4; y++)
{
if (s.isDerrivedFrom(pieces))
{
count++;
}
//all rotation calls rotate the piece / structure byt 90 degrees
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Y_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.X_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Z_AXIS));
}
}
return count;
}
我怎样才能改进这一点,这样我就不会重复相同的方向,即我只能签入 24 次迭代而不是 64 次。
24 次旋转中的每一次旋转都可以通过哪个面朝上(6 种可能性)和哪些面朝左(每个朝上的面有 4 种可能性)来唯一标识。
先用外循环确定朝上的面,再用内循环确定朝左的面似乎很容易。考虑到您的 rotate 调用需要的参数,我可能会这样做:
// Rotating around these axes in sequence will bring each face in turn
// to the top
private static GameObject.AXIS ROTATION_PATH = new GameObject.AXIS[] {
GameObject.AXIS.X_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.Z_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.X_AXIS,
GameObject.AXIS.Z_AXIS
};
public static int getPossibleSolutionCount(Map<PieceIndex, Piece> pieces)
{
int count = 0;
for (GameObject.AXIS path_axis: ROTATION_PATH)
{
for (int y = 0; y < 4; y++)
{
for (Solution s : solutions)
{
if (s.isDerivedFrom(pieces))
{
count++;
}
}
pieces.values().forEach(piece -> piece.rotate(GameObject.Axis.Y_AXIS));
}
pieces.values().forEach(piece -> piece.rotate(path_axis));
}
return count;
}
希望您了解它的工作原理。我假设了你的轴指向哪个方向以及事物旋转的方向,所以如果 ROTATION_PATH 没有为你做它应该做的事情,然后相应地调整它。