rubikscube

college code for finding optimal rubiks cube solutions in java

git clone https://9o.is/git/rubikscube.git

commit fc7d231b547c6bfb374f67aaa9ff60b66778e2b3
Author: Jul <jul@9o.is>
Date:   Fri, 19 Oct 2012 18:13:19 -0400

Incomplete rubik's cube problem.

Diffstat:
A.gitignore | 28++++++++++++++++++++++++++++
Asrc/Helper.java | 28++++++++++++++++++++++++++++
Asrc/KorfHeuristic.java | 108+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/PatternTable.java | 39+++++++++++++++++++++++++++++++++++++++
Asrc/RubiksColor.java | 30++++++++++++++++++++++++++++++
Asrc/RubiksCube.java | 457+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/RubiksRotation.java | 22++++++++++++++++++++++
Asrc/RubiksState.java | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/SavedRubiksState.java | 31+++++++++++++++++++++++++++++++
Asrc/ThreeDMatrix.java | 28++++++++++++++++++++++++++++
10 files changed, 813 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,28 @@ +*.class + +# text files +*.txt + +# Package Files # +*.jar +*.war +*.ear + +# Intellij IDEA +*.iws +*.ipr +*.iml + + +# Eclipse & Netbeans +.project +.settings +.classpath +.idea* +.scala_dependencies + +# swap files +*~ +*# +*.sw[op] +._* diff --git a/src/Helper.java b/src/Helper.java @@ -0,0 +1,28 @@ +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * Created with IntelliJ IDEA. + * User: julio + * Date: 10/18/12 + * Time: 7:46 AM + * To change this template use File | Settings | File Templates. + */ +public class Helper { + /** Encodes a string with md5. */ + public static String encodeMD5(String string) { + try { + MessageDigest md = MessageDigest.getInstance("MD5"); + byte[] mdbytes = md.digest(string.getBytes()); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < mdbytes.length; i++) { + sb.append(Integer.toString((mdbytes[i] & 0xff) + 0x100, 16).substring(1)); + } + + return sb.toString(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + return ""; + } + } +} diff --git a/src/KorfHeuristic.java b/src/KorfHeuristic.java @@ -0,0 +1,108 @@ +import java.util.LinkedList; +import java.util.Queue; + +/** + * Has the potential of generating tables of heuristics + * for the Rubik's cube. + */ +public class KorfHeuristic { + + private SavedRubiksState[] corners = new SavedRubiksState[44089920]; + private SavedRubiksState[] halfEdges = new SavedRubiksState[15360]; + private SavedRubiksState[] half2Edges = new SavedRubiksState[15360]; + + private PatternTable cornersTable; + private PatternTable halfEdgesTable; + private PatternTable half2EdgesTable; + + KorfHeuristic() { + cornersTable = new PatternTable("corners.txt"); + halfEdgesTable = new PatternTable("halfEdges.txt"); + half2EdgesTable = new PatternTable("half2Edges.txt"); + cornersTable.clearTable(); + halfEdgesTable.clearTable(); + half2EdgesTable.clearTable(); + } + + KorfHeuristic(PatternTable corners, + PatternTable halfEdges, + PatternTable half2Edges) { + this.cornersTable = corners; + this.halfEdgesTable = halfEdges; + this.half2EdgesTable = half2Edges; + this.cornersTable.clearTable(); + this.halfEdgesTable.clearTable(); + this.half2EdgesTable.clearTable(); + } + + public void generateTables() { + Queue<RubiksState> travq = new LinkedList<RubiksState>(); + travq.add(new RubiksCube().getState()); + int depth = 1; + RubiksState current; + while(!travq.isEmpty()) { + current = travq.poll(); + saveState(current, depth); + //TODO how to keep track of the depth + RubiksCube cube = new RubiksCube(current); + RubiksState[] childStates = cube.getNeighborStates(); + for(RubiksState state : childStates) { + queueChildState(travq, state); + } + } + + } + + // queue a state if its unique or it's not saved already + private void queueChildState(Queue<RubiksState> travq, RubiksState state) { + for(int i=0; i<corners.length; i++) { + if(Helper.encodeMD5(state.getState()).equals(corners[i].getKey())) + return; + } + travq.add(state); + } + + /** + * Uses IDA* search to find optimal path. + */ + public void lookupTable() { + RubiksCube cube = new RubiksCube(true); + // check if is goal state + // if not open its children + // search each and open child with lowest heuristic + current depth + // frontier queue to search next + // check if maxLimit depth has been passed + } + + public void saveState(RubiksState state, int depth) { + //corners + SavedRubiksState saved = + new SavedRubiksState(state.getState(),state.getCorners(), depth); + corners[corners.length-1] = saved; + cornersTable.updateTable(saved); + + //half edges + saved.setState(state.getHalfEdges()); + halfEdges[halfEdges.length-1] = saved; + halfEdgesTable.updateTable(saved); + + //second half edges + saved.setState(state.getHalf2Edges()); + half2Edges[half2Edges.length-1] = saved; + half2EdgesTable.updateTable(saved); + } + + public PatternTable getCornersTable() { + return cornersTable; + } + + public PatternTable getHalfEdgesTable() { + return halfEdgesTable; + } + + public PatternTable getHalf2EdgesTable() { + return half2EdgesTable; + } + + +} diff --git a/src/PatternTable.java b/src/PatternTable.java @@ -0,0 +1,39 @@ +import java.io.*; + +/** + * Stores a mapping of a key (hash) to two values (state,heuristic) in a file. + */ +public class PatternTable { + + /** The file that contains the pattern table. */ + private String file; + + PatternTable(String file) { + this.file = file; + } + + public void updateTable(SavedRubiksState saved) { + try { + BufferedWriter out = + new BufferedWriter(new FileWriter(file,true)); + out.write(saved.getKey()+":"+saved.getState()+":"+ + Integer.toString(saved.getHeuristic())+"\n"); + out.close(); + } catch (IOException e) { + System.err.println("Error: " + e.getMessage()); + } + } + + public void clearTable() { + try { + BufferedWriter out = + new BufferedWriter(new FileWriter(file)); + out.write(""); + out.close(); + } catch (IOException e) { + System.err.println("Error: " + e.getMessage()); + } + } + + +} diff --git a/src/RubiksColor.java b/src/RubiksColor.java @@ -0,0 +1,30 @@ +/** + * Different colors in a Rubik's cube. + */ +public enum RubiksColor { + RED ("R"), + GREEN ("G"), + BLUE ("B"), + YELLOW ("Y"), + ORANGE ("O"), + WHITE ("W"); + + private final String string; + + RubiksColor(String string) { + this.string = string; + } + + public String toString() { + return this.string; + } + + public static RubiksColor find(String string) { + if(string=="R") return RED; + else if(string=="G") return GREEN; + else if(string=="B") return BLUE; + else if(string=="Y") return YELLOW; + else if(string=="O") return ORANGE; + else return WHITE; + } +} diff --git a/src/RubiksCube.java b/src/RubiksCube.java @@ -0,0 +1,457 @@ +import java.util.Random; + +/** + * A 3 by 3, six sided Rubik's cube. + * + * @author Julio Enrique Cabrera + */ +public class RubiksCube { + /* Amount of sides or faces (6) in this cube. */ + private final int CUBE_SIDES = 6; + + /* Size of the cube. (3 by 3) */ + final int CUBE_SIZE = 3; + + /* 3-Dimensional array that stores the state of the cube. */ + private RubiksColor cube[][][]; + + /* Amount of moves */ + private int moves = 0; + + /** + * Initiates a rubik's cube at it's goal state. + */ + RubiksCube() { + cube = new RubiksColor[CUBE_SIDES][CUBE_SIZE][CUBE_SIZE]; + initGoalState(); + } + + /** + * Initiates a rubik's cube at it's goal state if parameter is + * false or it randomizes the state if parameter is true. + */ + RubiksCube(boolean random) { + cube = new RubiksColor[CUBE_SIDES][CUBE_SIZE][CUBE_SIZE]; + if(random) { + initGoalState(); + initRandomState(); + } else initGoalState(); + } + + /** + * Initiates a Rubik's cube from an existing state. + */ + RubiksCube(RubiksState state) { + cube = new RubiksColor[CUBE_SIDES][CUBE_SIZE][CUBE_SIZE]; + initState(state); + } + + /** + * Sets the state to the given state. + */ + public void initState(RubiksState state) { + final int CORNERS = 4; //corners per side + RubiksColor[] cornerColors = new RubiksColor[CUBE_SIDES*CORNERS]; + + int i=0; + for(char ch : state.getCorners().toCharArray()) { + cornerColors[i] = RubiksColor.find(Character.toString(ch)); i++; + } + for(i=0; i<CUBE_SIDES; i++) + for(int j=0; j<CORNERS; j++) { + if(j==0){ + cube[i][0][0] = cornerColors[i*CORNERS + j]; + } else if(j==1) { + cube[i][0][2] = cornerColors[i*CORNERS + j]; + } else if(j==2) { + cube[i][2][0] = cornerColors[i*CORNERS + j]; + } else if(j==3) { + cube[i][2][2] = cornerColors[i*CORNERS + j]; + } + } + + final int HALF_EDGES = 2; //half edges per side + RubiksColor[] halfEdgesColors = new RubiksColor[CUBE_SIDES*HALF_EDGES]; + + i=0; + for(char ch : state.getHalfEdges().toCharArray()) { + halfEdgesColors[i] = RubiksColor.find(Character.toString(ch)); i++; + } + for(i=0; i<CUBE_SIDES; i++) + for(int j=0; j<HALF_EDGES; j++) { + if(j==0){ + cube[i][0][1] = halfEdgesColors[i*HALF_EDGES + j]; + } else if(j==1) { + cube[i][1][0] = halfEdgesColors[i*HALF_EDGES + j]; + } + } + + i=0; + for(char ch : state.getHalf2Edges().toCharArray()) { + halfEdgesColors[i] = RubiksColor.find(Character.toString(ch)); i++; + } + for(i=0; i<CUBE_SIDES; i++) + for(int j=0; j<HALF_EDGES; j++) { + if(j==0){ + cube[i][1][2] = halfEdgesColors[i*HALF_EDGES + j]; + } else if(j==1) { + cube[i][2][1] = halfEdgesColors[i*HALF_EDGES + j]; + } + } + } + + /** + * Resets the rubik's cube at it's goal state. + */ + public void initGoalState() { + int side,row,column; + for (side=0; side<CUBE_SIDES; side++) + for(row=0; row<CUBE_SIZE; row++) + for (column=0; column<CUBE_SIZE; column++) { + if(side==0) cube[side][row][column]= RubiksColor.RED; + else if(side==1) cube[side][row][column]= RubiksColor.GREEN; + else if(side==2) cube[side][row][column]= RubiksColor.YELLOW; + else if(side==3) cube[side][row][column]= RubiksColor.BLUE; + else if(side==4) cube[side][row][column]= RubiksColor.ORANGE; + else cube[side][row][column]= RubiksColor.WHITE; + } + } + + /** + * Shuffles the rubik's cube to a random state. + */ + public void initRandomState() { + Random random = new Random(); + for(int i=0; i<100; i++) { + rotate(random.nextInt(CUBE_SIZE), RubiksRotation.randomRotation()); + } + } + + /** + * Rotates a piece of the cube to change its state. + * A maximum of 18 child states are available. + * @param piece Piece to rotate (0-2 if cube size is 3) + * @param rotation Type of rotation + */ + public void rotate(int piece, RubiksRotation rotation) { + switch (rotation) { + case VERTICAL_CLOCKWISE_90: + rotatePieceVerticalClockwise90(piece); + break; + case VERTICAL_COUNTERCLOCKWISE_90: + rotatePieceVerticalCounterClockwise90(piece); + break; + case VERTICAL_180_DEGREES: + rotatePieceVertical180(piece); + break; + case HORIZONTAL_CLOCKWISE_90: + rotatePieceHorizontalClockwise90(piece); + break; + case HORIZONTAL_COUNTERCLOCKWISE_90: + rotatePieceHorizontalCounterClockwise90(piece); + break; + case HORIZONTAL_180_DEGREES: + rotatePieceHorizontal180(piece); + break; + default: + break; + } + } + + /** + * Exports the current state of the rubik's cube. + * @return state of the current cube. + */ + public RubiksState getState() { + RubiksState state = new RubiksState(); + int side,row,column; + for(side=0; side<CUBE_SIDES; side++) + for(row=0; row<CUBE_SIZE; row++) + for (column=0; column<CUBE_SIZE; column++ ) { + if((row==0 || row==2) && (column==0 || column==2)) + state.setCorners(state.getCorners() + cube[side][row][column]); + else if((row==0 || row==2) && column==1) + state.setHalfEdges(state.getHalfEdges() + cube[side][row][column]); + else if(row==1 && (column==0 || column==2)) + state.setHalf2Edges(state.getHalf2Edges() + cube[side][row][column]); + } + return state; + } + + /** + * Rotates and returns all the possible children/neighbor states. + * @return an array of all neighbor states. + */ + public RubiksState[] getNeighborStates() { + RubiksState[] states = new RubiksState[18]; // 18 total states + for(int i=0; i<CUBE_SIZE; i++) { + //vertical + rotate(i,RubiksRotation.VERTICAL_CLOCKWISE_90); + states[0+i] = getState(); + rotate(i,RubiksRotation.VERTICAL_180_DEGREES); + states[3+i] = getState(); + rotate(i,RubiksRotation.VERTICAL_CLOCKWISE_90); //original + rotate(i,RubiksRotation.VERTICAL_180_DEGREES); + states[6+i] = getState(); + rotate(i,RubiksRotation.VERTICAL_180_DEGREES); //original + + //horizontal + rotate(i,RubiksRotation.HORIZONTAL_CLOCKWISE_90); + states[9+i] = getState(); + rotate(i,RubiksRotation.HORIZONTAL_180_DEGREES); + states[12+i] = getState(); + rotate(i,RubiksRotation.HORIZONTAL_CLOCKWISE_90); //original + rotate(i,RubiksRotation.HORIZONTAL_180_DEGREES); + states[15+i] = getState(); + rotate(i,RubiksRotation.HORIZONTAL_180_DEGREES); //original + } + return states; + } + + /** + * Prints the state of the cube in the console. + */ + public void printState() { + + int side,row,column; + for(side=0; side<CUBE_SIDES; side++) + for(row=0; row<CUBE_SIZE; row++) { + for (column=0; column<CUBE_SIZE; column++ ) { + if((side==0 || side==4 || side==5) && column==0) + System.out.print(" "); + + if(side==1 || side==2 || side==3) { + if(side==1) { + if(row==0) System.out.print(cube[side+row][row][column]); + else if(row==1) System.out.print(cube[side+row][row-1][column]); + else System.out.print(cube[side+row][row-2][column]); + } + if(side==2) { + if(row==0) System.out.print(cube[side-1][row+1][column]); + else if(row==1) System.out.print(cube[side][row][column]); + else System.out.print(cube[side+1][row-1][column]); + } else if(side==3) { + if(row==0) System.out.print(cube[side-2][row+2][column]); + else if(row==1) System.out.print(cube[side-1][row+1][column]); + else System.out.print(cube[side][row][column]); + } + //else System.out.print(threeD[side+(column-1)][row][column]); + if(row==2 && column==2) System.out.println(); + } else + System.out.print(cube[side][row][column]); + } + if(side==0 || side==4 || side==5) + System.out.println(); + } + + System.out.println(); + } + + private void rotatePieceVerticalClockwise90(int piece) { + if(!isValidPiece(piece)) return; + // change side 0 + RubiksColor side0row0 = setValue(0,0,piece, cube[5][0][piece]); + RubiksColor side0row1 = setValue(0,1,piece, cube[5][1][piece]); + RubiksColor side0row2 = setValue(0,2,piece, cube[5][2][piece]); + + // change side 2 + RubiksColor side2row0 = setValue(2,0,piece, side0row0); + RubiksColor side2row1 = setValue(2,1,piece, side0row1); + RubiksColor side2row2 = setValue(2,2,piece, side0row2); + + // change side 4 + RubiksColor side4row0 = setValue(4,0,piece, side2row0); + RubiksColor side4row1 = setValue(4,1,piece, side2row1); + RubiksColor side4row2 = setValue(4,2,piece, side2row2); + + // change side 5 + RubiksColor side5row0 = setValue(5,0,piece, side4row0); + RubiksColor side5row1 = setValue(5,1,piece, side4row1); + RubiksColor side5row2 = setValue(5,2,piece, side4row2); + + if(piece==0) rotateSide90Clockwise(1); + else if(piece==2) rotateSide90CounterClockwise(3); + } + + private void rotatePieceVerticalCounterClockwise90(int piece) { + if(!isValidPiece(piece)) return; + // change side 0 + RubiksColor side0row0 = setValue(0,0,piece, cube[2][0][piece]); + RubiksColor side0row1 = setValue(0,1,piece, cube[2][1][piece]); + RubiksColor side0row2 = setValue(0,2,piece, cube[2][2][piece]); + + // change side 5 + RubiksColor side5row0 = setValue(5,0,piece, side0row0); + RubiksColor side5row1 = setValue(5,1,piece, side0row1); + RubiksColor side5row2 = setValue(5,2,piece, side0row2); + + // change side 4 + RubiksColor side4row0 = setValue(4,0,piece, side5row0); + RubiksColor side4row1 = setValue(4,1,piece, side5row1); + RubiksColor side4row2 = setValue(4,2,piece, side5row2); + + // change side 2 + RubiksColor side2row0 = setValue(2,0,piece, side4row0); + RubiksColor side2row1 = setValue(2,1,piece, side4row1); + RubiksColor side2row2 = setValue(2,2,piece, side4row2); + + if(piece==0) rotateSide90CounterClockwise(1); + else if(piece==2) rotateSide90Clockwise(3); + } + + private void rotatePieceVertical180(int piece) { + if(!isValidPiece(piece)) return; + // switch side 0 with side 4 + switchValues(0, 0, piece, 4, 0, piece); + switchValues(0, 1, piece, 4, 1, piece); + switchValues(0, 2, piece, 4, 2, piece); + + // switch side 5 with side 2 + switchValues(5, 0, piece, 2, 0, piece); + switchValues(5, 1, piece, 2, 1, piece); + switchValues(5, 2, piece, 2, 2, piece); + + if(piece==0) rotateSide180(1); + else if(piece==2) rotateSide180(3); + } + + // rotate to left + private void rotatePieceHorizontalClockwise90(int piece) { + if(!isValidPiece(piece)) return; + // change side 1 + RubiksColor side1col0 = setValue(1,piece,0, cube[2][piece][0]); + RubiksColor side1col1 = setValue(1,piece,1, cube[2][piece][1]); + RubiksColor side1col2 = setValue(1,piece,2, cube[2][piece][2]); + + // change side 5 + RubiksColor side5col0 = setValue(5,piece,0, side1col0); + RubiksColor side5col1 = setValue(5,piece,1, side1col1); + RubiksColor side5col2 = setValue(5,piece,2, side1col2); + + // change side 3 + RubiksColor side3col0 = setValue(3,piece,0, side5col0); + RubiksColor side3col1 = setValue(3,piece,1, side5col1); + RubiksColor side3col2 = setValue(3,piece,2, side5col2); + + // change side 2 + RubiksColor side2col0 = setValue(2,piece,0, side3col0); + RubiksColor side2col1 = setValue(2,piece,1, side3col1); + RubiksColor side2col2 = setValue(2,piece,2, side3col2); + + if(piece==0) rotateSide90Clockwise(0); + else if(piece==2) rotateSide90CounterClockwise(4); + } + + // rotate to right + private void rotatePieceHorizontalCounterClockwise90(int piece) { + if(!isValidPiece(piece)) return; + // change side 1 + RubiksColor side1col0 = setValue(1,piece,0, cube[5][piece][0]); + RubiksColor side1col1 = setValue(1,piece,1, cube[5][piece][1]); + RubiksColor side1col2 = setValue(1,piece,2, cube[5][piece][2]); + + // change side 2 + RubiksColor side2col0 = setValue(2,piece,0, side1col0); + RubiksColor side2col1 = setValue(2,piece,1, side1col1); + RubiksColor side2col2 = setValue(2,piece,2, side1col2); + + // change side 3 + RubiksColor side3col0 = setValue(3,piece,0, side2col0); + RubiksColor side3col1 = setValue(3,piece,1, side2col1); + RubiksColor side3col2 = setValue(3,piece,2, side2col2); + + // change side 5 + RubiksColor side5col0 = setValue(5,piece,0, side3col0); + RubiksColor side5col1 = setValue(5,piece,1, side3col1); + RubiksColor side5col2 = setValue(5,piece,2, side3col2); + + if(piece==0) rotateSide90CounterClockwise(0); + else if(piece==2) rotateSide90Clockwise(4); + } + + private void rotatePieceHorizontal180(int piece) { + if(!isValidPiece(piece)) return; + // switch side 2 with side 5 + switchValues(2, piece, 0, 5, piece, 0); + switchValues(2, piece, 1, 5, piece, 1); + switchValues(2, piece, 2, 5, piece, 2); + + // switch side 1 with side 3 + switchValues(1, piece, 0, 3, piece, 0); + switchValues(1, piece, 1, 3, piece, 1); + switchValues(1, piece, 2, 3, piece, 2); + + if(piece==0) rotateSide180(0); + else if(piece==2) rotateSide180(4); + } + + // rotates the values in the same side. Does not manipulate any other side. + // the middle part never moves so there are 8 moves in total if its 3x3 + + + private void rotateSide90Clockwise(int side) { + if(!isValidSide(side)) return; + + // side corners + RubiksColor row0col0 = setValue(side,0,0, cube[side][2][0]); + RubiksColor row0col2 = setValue(side,0,2, row0col0); + RubiksColor row2col2 = setValue(side,2,2, row0col2); + RubiksColor row2col0 = setValue(side,2,0, row2col2); + + // side edges + RubiksColor row0col1 = setValue(side,0,1, cube[side][1][0]); + RubiksColor row1col2 = setValue(side,1,2, row0col1); + RubiksColor row2col1 = setValue(side,2,1, row1col2); + RubiksColor row1col0 = setValue(side,1,0, row2col1); + } + + private void rotateSide90CounterClockwise(int side) { + if(!isValidSide(side)) return; + + // side corners + RubiksColor row0col0 = setValue(side,0,0, cube[side][0][2]); + RubiksColor row2col0 = setValue(side,2,0, row0col0); + RubiksColor row2col2 = setValue(side,2,2, row2col0); + RubiksColor row0col2 = setValue(side,0,2, row2col2); + + // side edges + RubiksColor row0col1 = setValue(side,0,1, cube[side][1][2]); + RubiksColor row1col0 = setValue(side,1,0, row0col1); + RubiksColor row2col1 = setValue(side,2,1, row1col0); + RubiksColor row1col2 = setValue(side,1,2, row2col1); + } + + private void rotateSide180(int side) { + if(!isValidSide(side)) return; + // side corners + switchValues(side, 0, 0, side, 2, 2); + switchValues (side,2,0,side,0,2); + + // side edges + switchValues (side,0,1,side,2,1); + switchValues (side,1,0,side,1,2); + } + + + // Sets the value with a another and returns the old value. + private RubiksColor setValue(int i, int j, int k, RubiksColor value) { + RubiksColor oldValue = cube[i][j][k]; + cube[i][j][k] = value; + return oldValue; + } + + // Switches the values of one side-row-column coordinate with another. + private void switchValues(int _i, int _j, int _k, int i, int j, int k) { + RubiksColor oldValue = cube[_i][_j][_k]; + cube[_i][_j][_k] = cube[i][j][k]; + cube[i][j][k] = oldValue; + } + + private boolean isValidSide(int side) { + return side < CUBE_SIDES && side > -1; + } + + private boolean isValidPiece(int piece) { + return piece < CUBE_SIZE && piece > -1; + } +} diff --git a/src/RubiksRotation.java b/src/RubiksRotation.java @@ -0,0 +1,22 @@ +import java.util.*; + +/** + * Different possible rotation directions in Rubik's cube. + */ +public enum RubiksRotation { + VERTICAL_CLOCKWISE_90, + VERTICAL_COUNTERCLOCKWISE_90, + VERTICAL_180_DEGREES, + HORIZONTAL_CLOCKWISE_90, + HORIZONTAL_COUNTERCLOCKWISE_90, + HORIZONTAL_180_DEGREES; + + private static final List<RubiksRotation> VALUES = + Collections.unmodifiableList(Arrays.asList(values())); + private static final int SIZE = VALUES.size(); + private static final Random RANDOM = new Random(); + + public static RubiksRotation randomRotation() { + return VALUES.get(RANDOM.nextInt(SIZE)); + } +} diff --git a/src/RubiksState.java b/src/RubiksState.java @@ -0,0 +1,42 @@ +/** + * A Rubik's Cube State. + */ +public class RubiksState { + /* State of the corners. */ + private String corners; + + /* State of half of the edges. */ + private String halfEdges; + + /* State of half of the other edges. */ + private String half2Edges; + + public void setCorners(String corners) { + this.corners = corners; + } + + public void setHalfEdges(String halfEdges) { + this.halfEdges = halfEdges; + } + + public void setHalf2Edges(String half2Edges) { + this.half2Edges = half2Edges; + } + + public String getCorners() { + return corners; + } + + public String getHalfEdges() { + return halfEdges; + } + + public String getHalf2Edges() { + return half2Edges; + } + + /** All states combined. */ + public String getState() { + return getCorners() + getHalfEdges() + getHalf2Edges(); + } +} diff --git a/src/SavedRubiksState.java b/src/SavedRubiksState.java @@ -0,0 +1,31 @@ +/** + * Just a helper class. + */ +public class SavedRubiksState { + + private String key; + private String state; + private int heuristic; + + public SavedRubiksState(String key, String state, int heuristic) { + this.key = Helper.encodeMD5(key); + this.state = state; + this.heuristic = heuristic; + } + + public void setState(String state) { + this.state = state; + } + + public String getKey() { + return key; + } + + public String getState() { + return state; + } + + public int getHeuristic() { + return heuristic; + } +} diff --git a/src/ThreeDMatrix.java b/src/ThreeDMatrix.java @@ -0,0 +1,27 @@ +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +class ThreeDMatrix +{ + public static void main(String[] args) + { + /*RubiksCube cube = new RubiksCube(true); + String[][] export = cube.getState(); + String corners = export[0][0]; + String halfEdges = export[1][0]; + //String half2Edges = export[2][0]; + System.out.println(corners); + System.out.println(halfEdges); + //System.out.println(half2Edges); + + PatternTable cornersTable = new PatternTable("corners.txt"); + cornersTable.updateTable(corners, "1"); + cornersTable.updateTable(halfEdges, "2"); */ + //PatternTable cornersTable = new PatternTable("corners.txt"); + //System.out.println(cornersTable.valueOf("WYWWRORBRBYY")); + //cornersTable.clearTable(); + + + + } +} +\ No newline at end of file