-
Notifications
You must be signed in to change notification settings - Fork 0
/
second_phase.py
381 lines (362 loc) · 12 KB
/
second_phase.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
from notation import *
class second_phase(mycube):
#constructor gets current state (i.e, first stage solved) and initializes the super class (i.e the generic cube)
def __init__(self,c_state):
self.up = c_state.up
self.down = c_state.down
self.back = c_state.back
self.front = c_state.front
self.right = c_state.right
self.left = c_state.left
self.ans = []
#this is basically a controller method which calls other methods eho actually solve the cube and returns the ans for THIS STAGE
def solve(self):
self.set_conflicting_corners()
#print("--------------------------after adjusting corners-----------------------")
#self.print_cube_with_faces()
self.set_adjacent_corners_same()
#print("-----------------------after adjacent corners are same---------------------")
#self.print_cube_with_faces()
self.make_sides()
#print("---------------------------after makng sides-------------------------------")
return self.ans
#returns conflicting corners (i.e orange on up face or red on down face) of up face if face=0 else returns conflicting corners of down face
def get_conflicting_corners(self,face):
count = 0
conflicting_corner=[]
if face == 0:
for i in range(0,3,2):
# print(self.up[0])
if self.up[i] == 'o':
conflicting_corner.append(i)
count+=1
if self.up[i+6] == 'o':
count+=1
conflicting_corner.append(i+6)
else:
for i in range(0,3,2):
if self.down[i] == 'r':
conflicting_corner.append(i)
count+=1
if self.down[i+6] == 'r':
count+=1
conflicting_corner.append(i+6)
return count,conflicting_corner
#this basically is first step of 2A
def set_conflicting_corners(self):
# ans = []
# self.print_cube_with_faces()
adjacent_corner = {0:8,2:6,6:2,8:0}
while True:
n_conflicting_corners,conflicting_corners = self.get_conflicting_corners(0)
# print(n_conflicting_corners)
# print(conflicting_corners)
#no conflicting corners
if n_conflicting_corners==0:
break
elif n_conflicting_corners==1:
# self.print_cube_with_faces()
#rotate down face till upper conflicting corner is in cross-opposite of down-conflicting corner
while self.down[adjacent_corner[conflicting_corners[0]]] != 'r':
self.d()
self.ans.append('d')
#rotate face having upper-conflicting corner but not having down-conflicting twice
if conflicting_corners[0] in [0,6]:
self.l2()
self.ans.append('l2')
elif conflicting_corners[0] in [2,8]:
self.r2()
self.ans.append('r2')
elif n_conflicting_corners==2:
up_conf_corners = conflicting_corners
n_down_conf_corners,down_conf_corners = self.get_conflicting_corners(1)
if (self.is_adjacent(up_conf_corners[0],up_conf_corners[1])) and (self.is_adjacent(down_conf_corners[0],down_conf_corners[1])):
d1 = self.get_down_corner(up_conf_corners[0])
d2 = self.get_down_corner(up_conf_corners[1])
#print("in1")
#rotate to set set conflicting corners of down face to down of conflicting upper corners
while not (self.down[d1] == 'r' and self.down[d2] == 'r'):
self.d()
self.ans.append('d')
#rotate face having all conflicting corners
if (up_conf_corners[0] in [0,2]) and (up_conf_corners[1] in [0,2]):
self.b2()
self.ans.append('b2')
elif (up_conf_corners[0] in [2,8]) and (up_conf_corners[1] in [2,8]):
self.r2()
self.ans.append('r2')
elif (up_conf_corners[0] in [6,8]) and (up_conf_corners[1] in [6,8]):
self.f2()
self.ans.append('f2')
elif (up_conf_corners[0] in [0,6]) and (up_conf_corners[1] in [0,6]):
self.l2()
self.ans.append('l2')
break
elif (self.is_adjacent(up_conf_corners[0],up_conf_corners[1])) and (not self.is_adjacent(down_conf_corners[0],down_conf_corners[1])):
#print("in2")
#print(down_conf_corners[0],down_conf_corners[1])
#rotate face having two upper-conflicting corners
if (up_conf_corners[0] in [0,2]) and (up_conf_corners[1] in [0,2]):
self.b2()
self.ans.append('b2')
elif (up_conf_corners[0] in [2,8]) and (up_conf_corners[1] in [2,8]):
self.r2()
self.ans.append('r2')
elif (up_conf_corners[0] in [6,8]) and (up_conf_corners[1] in [6,8]):
self.f2()
self.ans.append('f2')
elif (up_conf_corners[0] in [0,6]) and (up_conf_corners[1] in [0,6]):
self.l2()
self.ans.append('l2')
elif ((not self.is_adjacent(up_conf_corners[0],up_conf_corners[1])) and (self.is_adjacent(down_conf_corners[0],down_conf_corners[1]))):
#rotate face having two down-conflicting corners
if ((down_conf_corners[0] in [0,2]) and (down_conf_corners[1] in [0,2])):
self.f2()
self.ans.append('f2')
elif ((down_conf_corners[0] in [2,8]) and (down_conf_corners[1] in [2,8])):
self.r2()
self.ans.append('r2')
elif ((down_conf_corners[0] in [6,8]) and (down_conf_corners[1] in [6,8])):
self.b2()
self.ans.append('b2')
elif ((down_conf_corners[0] in [0,6]) and (down_conf_corners[1] in [0,6])):
self.l2()
self.ans.append('l2')
elif ((not self.is_adjacent(up_conf_corners[0],up_conf_corners[1])) and (not self.is_adjacent(down_conf_corners[0],down_conf_corners[1]))):
#make upper conflicting diagonal perpendicular to down conflicting diagonal
#then rotate face having one upper-conflicting to get case 1 of this else-if ladder
if up_conf_corners[0] in [0,8]:
if down_conf_corners[0] not in [0,8]:
self.d()
self.ans.append('d')
self.r2()
self.ans.append('r2')
elif up_conf_corners[0] in [2,6]:
if down_conf_corners[0] not in [2,6]:
self.d()
self.ans.append('d')
self.l2()
self.ans.append('l2')
elif n_conflicting_corners==3:
#get 2 down-conflicting corners opposite to upper conflicting corner
if (0 not in conflicting_corners) or (6 not in conflicting_corners):
down_edges = [2,8]
elif (2 not in conflicting_corners) or (8 not in conflicting_corners):
down_edges = [0,6]
#rotate till down corners are conflicting
while self.down[down_edges[0]] != 'r' and self.down[down_edges[1]] != 'r':
self.d()
self.ans.append('d')
#rotate face having 2 conflicting corners
if down_edges[0]==2:
self.r2()
self.ans.append('r2')
elif down_edges[0]==0:
self.l2()
self.ans.append('l2')
elif n_conflicting_corners==4:
self.r2()
self.l2()
self.ans.extend(['r2','l2'])
break
return self.ans
#this makes adjacent corners on front,back,left and right same
def set_adjacent_corners_same(self):
#print("here")
while True:
# 0 = all mismatch | 1 = 1 match | 2 = all matched
up_state,down_state = self.get_layer_state()
#all 9 cases and their solutions
# print(up_state,down_state)
# print("in")
if up_state == 2 and down_state == 2:
# print([2,2])
break
elif up_state == 1 and down_state == 1:
# print([1,1])
while self.back[0] != self.back[2]:
self.u()
self.ans.append('u')
while self.front[6] != self.front[8]:
self.d()
self.ans.append('d')
self.do_algo(0)
elif up_state == 0 and down_state == 0:
# print([0,0])
self.r2()
self.f2()
self.r2()
self.ans.extend(['r2','f2','r2'])
elif up_state == 1 and down_state == 0:
# print([1,0])
while self.front[0] != self.front[2]:
self.u()
self.ans.append('u')
self.do_algo(0)
elif up_state == 0 and down_state == 1:
# print([0,1])
while self.front[6] != self.front[8]:
self.d()
self.ans.append('d')
self.do_algo(1)
elif up_state == 0 and down_state == 2:
# print([0,2])
self.do_algo(0)
elif up_state == 2 and down_state == 0:
# print([2,0])
self.do_algo(1)
elif up_state == 1 and down_state == 2:
# print([1,2])
while self.back[0] != self.back[2]:
self.u()
self.ans.append('u')
self.do_algo(0)
elif up_state == 2 and down_state == 1:
# print([2,1])
while self.back[6] != self.back[8]:
self.d()
self.ans.append('d')
self.do_algo(1)
#this checks whether 2 corners are adjacent or not
def is_adjacent(self,a,b):
# print(b)
adjacent_list = {0:[2,6] , 2:[0,8] , 6:[0,8] , 8:[2,6]}
return (a in adjacent_list[b])
#gives down corners
def get_down_corner(self,a):
down_dic = {0:6,2:8,6:0,8:2}
return down_dic[a]
#same as above but for edges
def get_down_edge(self,edge):
down_dic = {1:3,3:1,5:8,6:7,7:6,8:5,9:11,11:9}
return down_dic[edge]
#make all side faces b/g or w/y 2B
def make_sides(self):
edge_face_function_mapping = {1:self.f2,5:self.l2,6:self.r2,9:self.b2}
edge_face_move_mapping = {1:'f2',5:'l2',6:'r2',9:'b2'}
top_layer_edges = [1,5,6,9]
while True:
#all conflicting edges but non conflicting edges of top layer only
conf_edges,non_conf_edges = self.get_conflicting_edges()
n_conf_edges = len(conf_edges)
# print(n_conf_edges)
if self.front[0] not in ['b','g']:
self.u()
self.ans.append('u')
if self.front[6] not in ['b','g']:
self.d()
self.ans.append('d')
if n_conf_edges == 0:
break
elif n_conf_edges == 2:
for edge in top_layer_edges:
if self.is_conf_edge(edge):
edge_face_function_mapping[edge]()
self.ans.append(edge_face_move_mapping[edge])
if self.is_conf_edge(7):
self.d1()
self.ans.append('d1')
elif self.is_conf_edge(8):
self.d()
self.ans.append('d')
self.l2()
self.r2()
self.ans.append('l2')
self.ans.append('r2')
self.d()
self.ans.append('d')
else:
for edge in top_layer_edges:
if not self.is_conf_edge(edge):
if self.is_conf_edge(self.get_down_edge(edge)):
edge_face_function_mapping[edge]()
self.ans.append(edge_face_move_mapping[edge])
else:
self.d2()
edge_face_function_mapping[edge]()
self.ans.append('d2')
self.ans.append(edge_face_move_mapping[edge])
self.l2()
self.r2()
self.d1()
self.l2()
self.r2()
self.d()
self.ans.append('l2')
self.ans.append('r2')
self.ans.append('d1')
self.ans.append('l2')
self.ans.append('r2')
self.ans.append('d')
#state is how many corners mismatch (used in set_adjacent_corners_same)
def get_layer_state(self):
# ans = [0,0]
up_count = down_count = 0
mapping = {0:0,1:1,4:2}
faces = [self.front,self.right,self.back,self.left]
for face in faces:
if face[0] == face[2]:
up_count+=1
if face[6] == face[8]:
down_count+=1
return [mapping[up_count],mapping[down_count]]
#just a helper function to reduce code in set_adjacent_corners_same
def do_algo(self,flag):
if flag == 0:
self.r1()
self.f()
self.r1()
self.b2()
self.r()
self.f1()
self.r()
self.ans.extend(['r1','f','r1','b2','r','f1','r'])
else:
self.l1()
self.f()
self.l1()
self.b2()
self.l()
self.f1()
self.l()
self.ans.extend(['l1','f','l1','b2','l','f1','l'])
#edge is conflicting if it is residing between 2 corners whose color doesn't match with it (e.g. yellow in between b|g)
def get_conflicting_edges(self):
conf_edges = []
n_conf_edges = []
up_layer_edges = [1,5,6,9]
all_edges = [1,3,5,6,7,8,9,11]
for i in all_edges:
if self.is_conf_edge(i):
conf_edges.append(i)
elif i in up_layer_edges:
n_conf_edges.append(i)
return [conf_edges,n_conf_edges]
def is_conf_edge(self,edge):
up_layer_edges = [1,5,6,9]
down_layer_edges = [3,7,8,11]
front_edges = [1,3]
right_edges = [6,7]
back_edges = [9,11]
left_edges = [5,8]
edge_face_mapping = {
1:self.front,
3:self.front,
5:self.left,
6:self.right,
7:self.right,
8:self.left,
9:self.back,
11:self.back
}
face = edge_face_mapping[edge]
if(edge in up_layer_edges):
if (face[0] in ['b','g'] and face[1] in ['b','g']) or (face[0] in ['w','y'] and face[1] in ['w','y']):
return False
else:
return True
elif(edge in down_layer_edges):
if (face[7] in ['b','g'] and face[8] in ['b','g']) or (face[7] in ['w','y'] and face[8] in ['w','y']):
return False
else:
return True