/*
Edge Cubies:
14 2
1 15
13 3
0 12
1 13 0 12 3 15 2 14
9 20 20 11 11 22 22 9
21 8 8 23 23 10 10 21
17 5 18 6 19 7 16 4
18 6
5 19
17 7
4 16
Center Cubies:
0 1
3 2
20 21 8 9 16 17 12 13
23 22 11 10 19 18 15 14
4 5
7 6
* |************|
* |*U1**U2**U3*|
* |************|
* |*U4**U5**U6*|
* |************|
* |*U7**U8**U9*|
* |************|
* ************|************|************|************|
* *L1**L2**L3*|*F1**F2**F3*|*R1**R2**F3*|*B1**B2**B3*|
* ************|************|************|************|
* *L4**L5**L6*|*F4**F5**F6*|*R4**R5**R6*|*B4**B5**B6*|
* ************|************|************|************|
* *L7**L8**L9*|*F7**F8**F9*|*R7**R8**R9*|*B7**B8**B9*|
* ************|************|************|************|
* |************|
* |*D1**D2**D3*|
* |************|
* |*D4**D5**D6*|
* |************|
* |*D7**D8**D9*|
* |************|
*/
package cs.threephase;
import java.util.*;
import static cs.threephase.Moves.*;
import static cs.threephase.Util.*;
import static cs.threephase.Center1.symmove;
import static cs.threephase.Center1.symmult;
import static cs.threephase.Center1.syminv;
public class FullCube implements Comparable<FullCube> {
public static class ValueComparator implements Comparator<FullCube> {
public int compare(FullCube c1, FullCube c2) {
return c2.value - c1.value;
}
}
private EdgeCube edge;
private CenterCube center;
private CornerCube corner;
int value = 0;
boolean add1 = false;
int length1 = 0;
int length2 = 0;
int length3 = 0;
@Override
public int compareTo(FullCube c) {
return value - c.value;
}
public FullCube() {
edge = new EdgeCube();
center = new CenterCube();
corner = new CornerCube();
}
public FullCube(FullCube c) {
this();
copy(c);
}
public FullCube(Random r) {
edge = new EdgeCube(r);
center = new CenterCube(r);
corner = new CornerCube(r);
}
public FullCube(int[] moveseq) {
this();
for (int m : moveseq) {
doMove(m);
}
}
public void copy(FullCube c) {
edge.copy(c.edge);
center.copy(c.center);
corner.copy(c.corner);
this.value = c.value;
this.add1 = c.add1;
this.length1 = c.length1;
this.length2 = c.length2;
this.length3 = c.length3;
this.sym = c.sym;
for (int i=0; i<60; i++) {
this.moveBuffer[i] = c.moveBuffer[i];
}
this.moveLength = c.moveLength;
this.edgeAvail = c.edgeAvail;
this.centerAvail = c.centerAvail;
this.cornerAvail = c.cornerAvail;
}
// public void print() {
// getCenter().print();
// getEdge().print();
// }
public boolean checkEdge() {
return getEdge().checkEdge();
}
public String getMoveString(boolean inverse, boolean rotation) {
int[] fixedMoves = new int[moveLength - (add1 ? 2 : 0)];
int idx = 0;
for (int i=0; i<length1; i++) {
fixedMoves[idx++] = moveBuffer[i];
}
int sym = this.sym;
for (int i=length1 + (add1 ? 2 : 0); i<moveLength; i++) {
if (symmove[sym][moveBuffer[i]] >= dx1) {
fixedMoves[idx++] = symmove[sym][moveBuffer[i]] - 9;
int rot = move2rot[symmove[sym][moveBuffer[i]] - dx1];
sym = symmult[sym][rot];
} else {
fixedMoves[idx++] = symmove[sym][moveBuffer[i]];
}
}
int finishSym = symmult[syminv[sym]][Center1.getSolvedSym(getCenter())];
StringBuffer sb = new StringBuffer();
sym = finishSym;
if (inverse) {
for (int i=idx-1; i>=0; i--) {
int move = fixedMoves[i];
move = move / 3 * 3 + (2 - move % 3);
if (symmove[sym][move] >= dx1) {
sb.append(move2str[symmove[sym][move] - 9]).append(' ');
int rot = move2rot[symmove[sym][move] - dx1];
sym = symmult[sym][rot];
} else {
sb.append(move2str[symmove[sym][move]]).append(' ');
}
}
if (rotation) {
sb.append(Center1.rot2str[syminv[sym]] + " ");//cube rotation after solution. for wca scramble, it should be omitted.
}
} else {
for (int i=0; i<idx; i++) {
sb.append(move2str[fixedMoves[i]]).append(' ');
}
if (rotation) {
sb.append(Center1.rot2str[finishSym]);//cube rotation after solution.
}
}
return sb.toString();
}
private static int[] move2rot = {35, 1, 34, 2, 4, 6, 22, 5, 19};
String to333Facelet() {
char[] ret = new char[54];
getEdge().fill333Facelet(ret);
getCenter().fill333Facelet(ret);
getCorner().fill333Facelet(ret);
return new String(ret);
}
byte[] moveBuffer = new byte[60];
private int moveLength = 0;
private int edgeAvail = 0;
private int centerAvail = 0;
private int cornerAvail = 0;
int sym = 0;
void move(int m) {
moveBuffer[moveLength++] = (byte)m;
return;
}
void doMove(int m) {
getEdge().move(m);
getCenter().move(m);
getCorner().move(m % 18);
}
EdgeCube getEdge() {
while (edgeAvail < moveLength) {
edge.move(moveBuffer[edgeAvail++]);
}
return edge;
}
CenterCube getCenter() {
while (centerAvail < moveLength) {
center.move(moveBuffer[centerAvail++]);
}
return center;
}
CornerCube getCorner() {
while (cornerAvail < moveLength) {
corner.move(moveBuffer[cornerAvail++] % 18);
}
return corner;
}
}