rubikscube
college code for finding optimal rubiks cube solutions in java
git clone https://9o.is/git/rubikscube.git
RubiksPatternTable.java
(7961B)
1 import java.util.ArrayList;
2 import java.util.LinkedList;
3 import java.util.List;
4 import java.util.Queue;
5
6 /**
7 * Generates tables of ALL attainable Rubik's cube states alongside
8 * heuristics or the amount of moves to its goal state.
9 */
10 public class RubiksPatternTable {
11
12 /*
13 * All attainable corner states of a rubik's cube.
14 * There are 8! * 3^7 = 88,179,840 possible combination.
15 */
16 private byte[] corners =
17 new byte[88179840];
18
19 /*
20 * Half of all attainable edge states of a rubik's cube.
21 * There are 12!/6! * 2^6 = 42,577,920 possible combinations.
22 */
23 private byte[] halfEdges =
24 new byte[42577920];
25
26 /*
27 * Second half of all attainable edge states of a rubik's cube.
28 * There are 12!/6! * 2^6 = 42,577,920 possible combinations.
29 */
30 private byte[] half2Edges =
31 new byte[42577920];
32
33 /*
34 * All attainable corner states of a rubik's cube,
35 * alongside its heuristic, will be stored in a table (file).
36 */
37 private PatternTable cornersTable;
38
39 /*
40 * Half of all attainable edge states of a rubik's cube,
41 * alongside its heuristic, will be stored in a table (file).
42 */
43 private PatternTable halfEdgesTable;
44
45 /*
46 * Second half of all attainable edge states of a rubik's cube,
47 * alongside its heuristic, will be stored in a table (file).
48 */
49 private PatternTable half2EdgesTable;
50
51 /**
52 * Create a Rubik's Pattern Table.
53 */
54 public RubiksPatternTable() {
55 cornersTable = new PatternTable("corners.txt");
56 halfEdgesTable = new PatternTable("halfEdges.txt");
57 half2EdgesTable = new PatternTable("half2Edges.txt");
58 transferCorners(cornersTable.readTable());
59 transferHalfEdge(halfEdgesTable.readTable());
60 transferHalf2Edge(half2EdgesTable.readTable());
61 }
62
63 /**
64 * Create a Rubik's Pattern Table with specified files.
65 * @param corners File to store corner states.
66 * @param halfEdges File to store half of the edge states.
67 * @param half2Edges File to store other half of the edge states.
68 */
69 RubiksPatternTable(PatternTable corners,
70 PatternTable halfEdges,
71 PatternTable half2Edges) {
72 this.cornersTable = corners;
73 this.halfEdgesTable = halfEdges;
74 this.half2EdgesTable = half2Edges;
75 transferCorners(cornersTable.readTable());
76 transferHalfEdge(halfEdgesTable.readTable());
77 transferHalf2Edge(half2EdgesTable.readTable());
78 }
79
80 /**
81 * Generates a pattern table of all possible rubik's cube states.
82 * Tables are separated by corners and half of the edges.
83 * @throws Exception
84 */
85 public void generateTables() throws Exception {
86 // start at the goal state and add it to queue
87 RubiksState rootCube =
88 new RubiksState(RubiksCube.GOAL,1);
89
90 Queue<RubiksState> travq = new LinkedList<RubiksState>();
91 travq.add(rootCube);
92
93 // traverse the queue and handle appropriately
94 RubiksState current;
95 while(!travq.isEmpty()) {
96 try {
97 // poll the queue and convert it to state and cube
98 // for easier manipulation
99 current = travq.poll();
100 RubiksCube cube = new RubiksCube(current);
101
102 // iterate the current cube's neighbors; add to queue
103 // if the state hasn't been added yet
104 for(RubiksState neighbor : cube.getNeighborStates()) {
105 if(corners[neighbor.getCorners().hashState()]==0 &&
106 halfEdges[neighbor.getHalfEdges().hashState()]==0 &&
107 half2Edges[neighbor.getHalf2Edges().hashState()]==0)
108 travq.add(new RubiksState(
109 neighbor,
110 current.getHeuristic()+1));
111 }
112
113 // save corner state to array and table
114 RubiksSubState cornerstate =
115 new RubiksCornerState(
116 current.getCorners().toString(),
117 current.getHeuristic());
118 int hash = cornerstate.hashState();
119 if(corners[hash] == 0) {
120 corners[hash] = cornerstate.getHeuristic();
121 cornersTable.updateTable(hash, cornerstate.getHeuristic());
122 }
123
124 // save first set of edges to array and table
125 RubiksSubState halfedgestate =
126 new RubiksHalfEdgeState(
127 current.getHalfEdges().toString(),
128 current.getHeuristic());
129 hash = halfedgestate.hashState();
130 if(halfEdges[hash] == 0) {
131 halfEdges[hash] = halfedgestate.getHeuristic();
132 halfEdgesTable.updateTable(hash, halfedgestate.getHeuristic());
133 }
134
135 // save second set of edges to array and table
136 RubiksSubState half2edgestate =
137 new RubiksHalfEdgeState(
138 current.getHalf2Edges().toString(),
139 current.getHeuristic());
140 hash = half2edgestate.hashState();
141 if(half2Edges[hash] == 0) {
142 half2Edges[hash] = half2edgestate.getHeuristic();
143 half2EdgesTable.updateTable(hash, half2edgestate.getHeuristic());
144 }
145
146 /*System.out.println(
147 "Added State: "+current.getState() +
148 " -> Heuristic: "+current.getHeuristic());*/
149
150 } catch (Exception e) {
151 e.printStackTrace();
152 }
153 }
154 }
155
156 /* Checks if current rubik's state is unique among a group of cubes. */
157 private boolean isCubeUnique(List<RubiksCube> cubes, RubiksState current) {
158 for(RubiksCube check : cubes) {
159 if(check.isEqualTo(new RubiksCube(current)))
160 return false;
161 }
162 return true;
163 }
164
165 /* Transfers table state to array. */
166 private void transferCorners(byte[] values) {
167 for(int i=0; i<corners.length; i++) {
168 corners[i] = values[i];
169 }
170 }
171
172 /* Transfers table state to array. */
173 private void transferHalfEdge(byte[] values) {
174 for(int i=0; i<halfEdges.length; i++) {
175 halfEdges[i] = values[i];
176 }
177 }
178
179 /* Transfers table state to array. */
180 private void transferHalf2Edge(byte[] values) {
181 for(int i=0; i<half2Edges.length; i++) {
182 half2Edges[i] = values[i];
183 }
184 }
185
186 /**
187 * Retrieve pattern table of all corner states.
188 * @return Pattern table of all corner states.
189 */
190 public PatternTable getCornersTable() {
191 return cornersTable;
192 }
193
194 /**
195 * Retrieve pattern table for the first half of all edge states.
196 * @return Pattern table for the first half of all edge states.
197 */
198 public PatternTable getHalfEdgesTable() {
199 return halfEdgesTable;
200 }
201
202 /**
203 * Retrieve pattern table for the second half of all edge states.
204 * @return Pattern table for the second half of all edge states.
205 */
206 public PatternTable getHalf2EdgesTable() {
207 return half2EdgesTable;
208 }
209
210 /**
211 * Retrieve all corner states.
212 * @return all corner states.
213 */
214 public byte[] getCorners() {
215 return corners;
216 }
217
218 /**
219 * Retrieve first half of all edge states.
220 * @return first half of all edge states.
221 */
222 public byte[] getHalfEdges() {
223 return halfEdges;
224 }
225
226 /**
227 * Retrieve second half of all edge states.
228 * @return second half of all edge states.
229 */
230 public byte[] getHalf2Edges() {
231 return half2Edges;
232 }
233 }