Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions src/main/java/hse/java/practice/task1/Permutations.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package hse.java.practice.task1;

import java.util.Arrays;
import java.util.stream.*;
import java.util.stream.IntStream;

public class Permutations {
static final int[] CURR_EDGES_ORDER = {2, 4, 3, 5, 0, 1};
public static final int G_SIZE = 48;

// Циклы перестановок для левой грани по часовой стрелке
static final int[][] L_CW = {
{1, 3, 8, 6},
{2, 5, 7, 4},
{33, 9, 41, 32},
{36, 12, 44, 29},
{38, 14, 46, 27}
};

// Циклы перестановок для передней грани по часовой стрелке
static final int[][] F_CW = {
{9, 11, 16, 14},
{10, 13, 15, 12},
{38, 17, 43, 8},
{39, 20, 42, 5},
{40, 22, 41, 3}
};

// Циклы перестановок для правой грани по часовой стрелке
static final int[][] R_CW = {
{17, 19, 24, 22},
{18, 21, 23, 20},
{48, 16, 40, 25},
{45, 13, 37, 28},
{43, 11, 35, 30}
};

// Циклы перестановок для задней грани по часовой стрелке
static final int[][] B_CW = {
{25, 27, 32, 30},
{26, 29, 31, 28},
{19, 33, 6, 48},
{21, 34, 4, 47},
{24, 35, 1, 46}
};

// Циклы перестановок для верхней грани по часовой стрелке
static final int[][] U_CW = {
{33, 35, 40, 38},
{34, 37, 39, 36},
{25, 17, 9, 1},
{26, 18, 10, 2},
{27, 19, 11, 3}
};

// Циклы перестановок для нижней грани по часовой стрелке
static final int[][] D_CW = {
{41, 43, 48, 46},
{42, 45, 47, 44},
{6, 14, 22, 30},
{7, 15, 23, 31},
{8, 16, 24, 32}
};

// То же самое, но против часовой
static final int[][] U_CCW = reverseCycles(U_CW);
static final int[][] D_CCW = reverseCycles(D_CW);
static final int[][] L_CCW = reverseCycles(L_CW);
static final int[][] R_CCW = reverseCycles(R_CW);
static final int[][] F_CCW = reverseCycles(F_CW);
static final int[][] B_CCW = reverseCycles(B_CW);

private static int[][] reverseCycles(int[][] cs) {
return Arrays.stream(cs)
.map(c -> {
final int cLen = c.length;
int[] rev = new int[cLen];
rev[0] = c[0];
IntStream.range(1, cLen).forEach(i -> rev[i] = c[cLen - i]);
return rev;
})
.toArray(int[][]::new);
}
}
92 changes: 83 additions & 9 deletions src/main/java/hse/java/practice/task1/RubiksCube.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,15 @@
* Необходимо реализовать интерфейс Cube
* При повороте передней грани, меняются верх низ право и лево
*/
public class RubiksCube {
public class RubiksCube implements Cube{

private static final int EDGES_COUNT = 6;
private static final int EDGES_COUNT = 6;
private static final int EDGE_SIZE = 3;
private static final int CENTER_INDEX = 5;
private static final int FIXED_ELEM = 8;

private final Edge[] edges = new Edge[EDGES_COUNT];
private final int[] states;

/**
* Создать валидный собранный кубик
Expand All @@ -20,22 +24,92 @@ public class RubiksCube {
* ...
*/
public RubiksCube() {
CubeColor[] colors = CubeColor.values();
for (int i = 0; i < 6; i++) {
edges[i] = new Edge(colors[i]);
}
CubeColor[] colors = CubeColor.values();
for (int i = 0; i < EDGES_COUNT; i++) edges[i] = new Edge(colors[i]);

states = new int[Permutations.G_SIZE + 1];
for (int i = 1; i < Permutations.G_SIZE + 1; i++) states[i] = i;
}

public void front(RotateDirection direction) {
public Edge[] getEdges() {
for (int i = 0; i < EDGES_COUNT; i++) edges[Permutations.CURR_EDGES_ORDER[i]].setParts(buildEdge(i));
return edges;
}

@Override
public void front(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.F_CW : Permutations.F_CCW);
}

public Edge[] getEdges() {
return edges;
@Override
public void back(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.B_CW : Permutations.B_CCW);
}

@Override
public String toString() {
return Arrays.toString(edges);
}

@Override
public void left(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.L_CW : Permutations.L_CCW);
}

@Override
public void right(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.R_CW : Permutations.R_CCW);
}

@Override
public void up(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.U_CW : Permutations.U_CCW);
}

@Override
public void down(RotateDirection direction) {
applyCyclesToStates(direction == RotateDirection.CLOCKWISE ? Permutations.D_CW : Permutations.D_CCW);
}

private void applyCycleToState(int[] c) {
final int cLen = c.length;
int prev = states[c[cLen - 1]];
for (int i = 0; i < cLen; i++) {
int cur = states[c[i]];
states[c[i]] = prev;
prev = cur;
}
}

private void applyCyclesToStates(int[][] cs) {
for (int[] c : cs) applyCycleToState(c);
}

private static int toElemPos(int x, int y) {
int pos = x + y * EDGE_SIZE + 1;
return pos > CENTER_INDEX ? pos - 1 : pos;
}

private static boolean isCenter(int x, int y) {
return x == 1 && y == 1;
}

private CubeColor centerColor(int edgeIndex) {
return CubeColor.values()[Permutations.CURR_EDGES_ORDER[edgeIndex]];
}

private CubeColor elemColor(int edgeIndex, int pos) {
int stateIndex = states[edgeIndex * FIXED_ELEM + pos];
int front = (stateIndex - 1) / FIXED_ELEM;
return CubeColor.values()[Permutations.CURR_EDGES_ORDER[front]];
}

private CubeColor[][] buildEdge(int edgeIndex) {
CubeColor[][] newEdge = new CubeColor[EDGE_SIZE][EDGE_SIZE];
for (int y = 0; y < EDGE_SIZE; y++) {
for (int x = 0; x < EDGE_SIZE; x++)
newEdge[y][x] = isCenter(x, y) ? centerColor(edgeIndex) : elemColor(edgeIndex, toElemPos(x, y));
}
return newEdge;
}
}