def last_layer_corners_position(self): self.move("X X") move_1 = "Li Fi L D F Di Li F L F F " move_2 = "F Li Fi L D F Di Li F L F " c1 = self.cube.find_piece(self.cube.front_color(), self.cube.right_color(), self.cube.down_color()) c2 = self.cube.find_piece(self.cube.front_color(), self.cube.left_color(), self.cube.down_color()) c3 = self.cube.find_piece(self.cube.front_color(), self.cube.right_color(), self.cube.up_color()) c4 = self.cube.find_piece(self.cube.front_color(), self.cube.left_color(), self.cube.up_color()) if c4.pos == Point(1, -1, 1): self.move(move_1 + "Zi " + move_1 + " Z") elif c4.pos == Point(1, 1, 1): self.move("Z " + move_2 + " Zi") elif c4.pos == Point(-1, -1, 1): self.move("Zi " + move_1 + " Z") assert c4.pos == Point(-1, 1, 1) if c2.pos == Point(1, 1, 1): self.move(move_2 + move_1) elif c2.pos == Point(1, -1, 1): self.move(move_1) assert c2.pos == Point(-1, -1, 1) if c3.pos == Point(1, -1, 1): self.move(move_2) assert c3.pos == Point(1, 1, 1) assert c1.pos == Point(1, -1, 1) self.move("Xi Xi")
def _from_cube(self, c): self.faces = [ Piece(pos=Point(p.pos), colors=p.colors) for p in c.faces ] self.edges = [ Piece(pos=Point(p.pos), colors=p.colors) for p in c.edges ] self.corners = [ Piece(pos=Point(p.pos), colors=p.colors) for p in c.corners ] self.pieces = self.faces + self.edges + self.corners
def test_point_neq(self): points = [ Point(1, 2, 3), Point(1, 2, 4), Point(1, 3, 3), Point(2, 2, 3) ] for i in range(len(points)): for j in range(i + 1, len(points)): self.assertNotEqual(points[i], points[j]) self.assertTrue(points[i] != points[j]) self.assertFalse(points[i] == points[j])
def setUp(self): self.A = Matrix(1, 2, 3, 4, 5, 6, 7, 8, 9) self.B = Matrix([9, 8, 7, 6, 5, 4, 3, 2, 1]) self.C = Matrix([[3, 2, 1], [6, 5, 4], [9, 8, 7]]) self.D = Matrix(x for x in range(11, 20)) self.p = Point(1, 2, 3)
def get_piece(self, x, y, z): """ :return: the Piece at the given Point """ point = Point(x, y, z) for p in self.pieces: if p.pos == point: return p
def last_layer_corners_position(self): self.move("X X") # UP face: # 4-3 # --- # 2-1 move_1 = "Li Fi L D F Di Li F L F F " # swaps 1 and 2 move_2 = "F Li Fi L D F Di Li F L F " # swaps 1 and 3 c1 = self.cube.find_piece(self.cube.front_color(), self.cube.right_color(), self.cube.down_color()) c2 = self.cube.find_piece(self.cube.front_color(), self.cube.left_color(), self.cube.down_color()) c3 = self.cube.find_piece(self.cube.front_color(), self.cube.right_color(), self.cube.up_color()) c4 = self.cube.find_piece(self.cube.front_color(), self.cube.left_color(), self.cube.up_color()) # place corner 4 if c4.pos == Point(1, -1, 1): self.move(move_1 + "Zi " + move_1 + " Z") elif c4.pos == Point(1, 1, 1): self.move("Z " + move_2 + " Zi") elif c4.pos == Point(-1, -1, 1): self.move("Zi " + move_1 + " Z") assert c4.pos == Point(-1, 1, 1) # place corner 2 if c2.pos == Point(1, 1, 1): self.move(move_2 + move_1) elif c2.pos == Point(1, -1, 1): self.move(move_1) assert c2.pos == Point(-1, -1, 1) # place corner 3 and corner 1 if c3.pos == Point(1, -1, 1): self.move(move_2) assert c3.pos == Point(1, 1, 1) assert c1.pos == Point(1, -1, 1) self.move("Xi Xi")
def _handle_last_layer_state2(self, br_edge, bl_edge, bu_edge, bd_edge, cycle_move): if DEBUG: print("_handle_last_layer_state2") def correct_edge(): piece = self.cube[cube.LEFT + cube.FRONT] if piece.colors[2] == self.cube.front_color( ) and piece.colors[0] == self.cube.left_color(): return piece piece = self.cube[cube.RIGHT + cube.FRONT] if piece.colors[2] == self.cube.front_color( ) and piece.colors[0] == self.cube.right_color(): return piece piece = self.cube[cube.UP + cube.FRONT] if piece.colors[2] == self.cube.front_color( ) and piece.colors[1] == self.cube.up_color(): return piece piece = self.cube[cube.DOWN + cube.FRONT] if piece.colors[2] == self.cube.front_color( ) and piece.colors[1] == self.cube.down_color(): return piece count = 0 while True: edge = correct_edge() if edge == None: self.move(cycle_move) else: break count += 1 if count % 3 == 0: self.move("Z") if count == 12: raise Exception("Stuck in loop - unsolvable cube:\n" + str(self.cube)) while edge.pos != Point(-1, 0, 1): self.move("Z") assert self.cube[cube.LEFT + cube.FRONT].colors[2] == self.cube.front_color() and \ self.cube[cube.LEFT + cube.FRONT].colors[0] == self.cube.left_color()
def _cross_left_or_right(self, edge_piece, face_piece, face_color, move_1, move_2): # don't do anything if piece is in correct place if (edge_piece.pos == (face_piece.pos.x, face_piece.pos.y, 1) and edge_piece.colors[2] == self.cube.front_color()): return # ensure piece is at z = -1 undo_move = None if edge_piece.pos.z == 0: pos = Point(edge_piece.pos) pos.x = 0 # pick the UP or DOWN face cw, cc = cube.get_rot_from_face(pos) if edge_piece.pos in (cube.LEFT + cube.UP, cube.RIGHT + cube.DOWN): self.move(cw) undo_move = cc else: self.move(cc) undo_move = cw elif edge_piece.pos.z == 1: pos = Point(edge_piece.pos) pos.z = 0 cw, cc = cube.get_rot_from_face(pos) self.move("{0} {0}".format(cc)) # don't set the undo move if the piece starts out in the right position # (with wrong orientation) or we'll screw up the remainder of the algorithm if edge_piece.pos.x != face_piece.pos.x: undo_move = "{0} {0}".format(cw) assert edge_piece.pos.z == -1 # piece is at z = -1, rotate to correct face (LEFT or RIGHT) count = 0 while (edge_piece.pos.x, edge_piece.pos.y) != (face_piece.pos.x, face_piece.pos.y): self.move("B") count += 1 if count == 10: raise Exception("Stuck in loop - unsolvable cube?\n" + str(self.cube)) # if we moved a correctly-placed piece, restore it if undo_move: self.move(undo_move) # the piece is on the correct face on plane z = -1, but has two orientations if edge_piece.colors[0] == face_color: self.move(move_1) else: self.move(move_2)
def place_frd_corner(self, corner_piece, right_piece, down_piece, front_color): # rotate to z = -1 if corner_piece.pos.z == 1: pos = Point(corner_piece.pos) pos.x = pos.z = 0 cw, cc = cube.get_rot_from_face(pos) # be careful not to screw up other pieces on the front face count = 0 undo_move = cc while corner_piece.pos.z != -1: self.move(cw) count += 1 if count > 1: # go the other direction because I don't know which is which. # we need to do only one flip (net) or we'll move other # correctly-placed corners out of place. for _ in range(count): self.move(cc) count = 0 while corner_piece.pos.z != -1: self.move(cc) count += 1 undo_move = cw self.move("B") for _ in range(count): self.move(undo_move) # rotate piece to be directly below its destination while (corner_piece.pos.x, corner_piece.pos.y) != (right_piece.pos.x, down_piece.pos.y): self.move("B") # there are three possible orientations for a corner if corner_piece.colors[0] == front_color: self.move("B D Bi Di") elif corner_piece.colors[1] == front_color: self.move("Bi Ri B R") else: self.move("Ri B B R Bi Bi D Bi Di")
def place_frd_corner(self, corner_piece, right_piece, down_piece, front_color): if corner_piece.pos.z == 1: pos = Point(corner_piece.pos) pos.x = pos.z = 0 cw, cc = cube.get_rot_from_face(pos) # be careful not to screw up other pieces on the front face count = 0 undo_move = cc while corner_piece.pos.z != -1: self.move(cw) count += 1 if count > 1:. for _ in range(count): self.move(cc) count = 0 while corner_piece.pos.z != -1: self.move(cc) count += 1 undo_move = cw self.move("B") for _ in range(count): self.move(undo_move) while (corner_piece.pos.x, corner_piece.pos.y) != (right_piece.pos.x, down_piece.pos.y): self.move("B") # there are three possible orientations for a corner if corner_piece.colors[0] == front_color: self.move("B D Bi Di") elif corner_piece.colors[1] == front_color: self.move("Bi Ri B R") else: self.move("Ri B B R Bi Bi D Bi Di")
def _cross_left_or_right(self, edge_piece, face_piece, face_color, move_1, move_2): if (edge_piece.pos == (face_piece.pos.x, face_piece.pos.y, 1) and edge_piece.colors[2] == self.cube.front_color()): return undo_move = None if edge_piece.pos.z == 0: pos = Point(edge_piece.pos) pos.x = 0 cw, cc = cube.get_rot_from_face(pos) if edge_piece.pos in (cube.LEFT + cube.UP, cube.RIGHT + cube.DOWN): self.move(cw) undo_move = cc else: self.move(cc) undo_move = cw elif edge_piece.pos.z == 1: pos = Point(edge_piece.pos) pos.z = 0 cw, cc = cube.get_rot_from_face(pos) self.move("{0} {0}".format(cc)) # don't set the undo move if the piece starts out in the right position if edge_piece.pos.x != face_piece.pos.x: undo_move = "{0} {0}".format(cw) assert edge_piece.pos.z == -1 #rotate to correct face (LEFT or RIGHT) count = 0 while (edge_piece.pos.x, edge_piece.pos.y) != (face_piece.pos.x, face_piece.pos.y): self.move("B") count += 1 if count == 10: raise Exception("Stuck in loop - unsolvable cube?\n" + str(self.cube)) # if we moved a correctly-placed piece, restore it if undo_move: self.move(undo_move) if edge_piece.colors[0] == face_color: self.move(move_1) else: self.move(move_2)
class TestPoint(unittest.TestCase): def setUp(self): self.p = Point(1, 2, 3) self.q = Point(2, 5, 9) self.r = Point(2, 2, 3) def test_point_constructor(self): self.assertEqual(self.p.x, 1) self.assertEqual(self.p.y, 2) self.assertEqual(self.p.z, 3) def test_point_count(self): self.assertEqual(self.r.count(2), 2) self.assertEqual(self.r.count(3), 1) self.assertEqual(self.r.count(5), 0) self.assertEqual(Point(9, 9, 9).count(9), 3) def test_point_eq(self): pp = Point(self.p.x, self.p.y, self.p.z) self.assertEqual(self.p, pp) self.assertTrue(self.p == pp) self.assertTrue(self.p == (1, 2, 3)) self.assertTrue(self.p == [1, 2, 3]) def test_point_neq(self): points = [ Point(1, 2, 3), Point(1, 2, 4), Point(1, 3, 3), Point(2, 2, 3) ] for i in range(len(points)): for j in range(i + 1, len(points)): self.assertNotEqual(points[i], points[j]) self.assertTrue(points[i] != points[j]) self.assertFalse(points[i] == points[j]) def test_point_add(self): self.assertEqual(self.p + self.q, Point(3, 7, 12)) def test_point_iadd(self): self.p += self.q self.assertEqual(self.p, Point(3, 7, 12)) def test_point_sub(self): self.assertEqual(self.p - self.q, Point(-1, -3, -6)) def test_point_isub(self): self.p -= self.q self.assertEqual(self.p, Point(-1, -3, -6)) def test_point_scale(self): self.assertEqual(self.p * 3, Point(3, 6, 9)) def test_point_dot_product(self): self.assertEqual(self.p.dot(self.q), 39) def test_point_cross_produce(self): self.assertEqual(self.p.cross(self.q), Point(3, -3, 1)) def test_to_tuple(self): self.assertEqual(tuple(self.p), (1, 2, 3)) def test_to_list(self): self.assertEqual(list(self.p), [1, 2, 3]) def test_from_tuple(self): self.assertEqual(Point((1, 2, 3)), self.p) def test_from_list(self): self.assertEqual(Point([1, 2, 3]), self.p) def test_point_str(self): self.assertEqual(str(self.p), "(1, 2, 3)") def test_point_repr(self): self.assertEqual(repr(self.p), "Point(1, 2, 3)") def test_point_iter(self): ii = iter(self.p) self.assertEqual(1, next(ii)) self.assertEqual(2, next(ii)) self.assertEqual(3, next(ii)) self.assertRaises(StopIteration, ii.__next__) def test_point_getitem(self): self.assertEqual(self.p[0], 1) self.assertEqual(self.p[1], 2) self.assertEqual(self.p[2], 3)
def test_point_cross_produce(self): self.assertEqual(self.p.cross(self.q), Point(3, -3, 1))
def test_point_scale(self): self.assertEqual(self.p * 3, Point(3, 6, 9))
def test_point_isub(self): self.p -= self.q self.assertEqual(self.p, Point(-1, -3, -6))
def test_point_sub(self): self.assertEqual(self.p - self.q, Point(-1, -3, -6))
def test_point_iadd(self): self.p += self.q self.assertEqual(self.p, Point(3, 7, 12))
def test_point_add(self): self.assertEqual(self.p + self.q, Point(3, 7, 12))
class TestPoint(unittest.TestCase): def setUp(self): self.p = Point(1, 2, 3) self.q = Point(2, 5, 9) self.r = Point(2, 2, 3) def test_point_constructor(self): self.assertEqual(self.p.x, 1) self.assertEqual(self.p.y, 2) self.assertEqual(self.p.z, 3) def test_point_count(self): self.assertEqual(self.r.count(2), 2) self.assertEqual(self.r.count(3), 1) self.assertEqual(self.r.count(5), 0) def test_point_eq(self): pp = Point(self.p.x, self.p.y, self.p.z) self.assertEqual(self.p, pp) self.assertTrue(self.p == pp) def test_point_neq(self): points = [Point(1, 2, 3), Point(1, 2, 4), Point(1, 3, 3), Point(2, 2, 3)] for i in xrange(len(points)): for j in xrange(i + 1, len(points)): self.assertNotEquals(points[i], points[j]) self.assertTrue(points[i] != points[j]) self.assertFalse(points[i] == points[j]) def test_point_add(self): self.assertEqual(self.p + self.q, Point(3, 7, 12)) def test_point_iadd(self): self.p += self.q self.assertEqual(self.p, Point(3, 7, 12)) def test_point_sub(self): self.assertEqual(self.p - self.q, Point(-1, -3, -6)) def test_point_isub(self): self.p -= self.q self.assertEqual(self.p, Point(-1, -3, -6)) def test_point_scale(self): self.assertEqual(self.p * 3, Point(3, 6, 9)) def test_point_dot_product(self): self.assertEqual(self.p.dot(self.q), 39) def test_point_cross_produce(self): self.assertEqual(self.p.cross(self.q), Point(3, -3, 1)) def test_to_tuple(self): self.assertEqual(tuple(self.p), (1, 2, 3)) def test_to_list(self): self.assertEqual(list(self.p), [1, 2, 3]) def test_from_tuple(self): self.assertEqual(Point((1, 2, 3)), self.p) def test_from_list(self): self.assertEqual(Point([1, 2, 3]), self.p) def test_point_str(self): self.assertEqual(str(self.p), "(1, 2, 3)") def test_point_repr(self): self.assertEqual(repr(self.p), "Point(1, 2, 3)") def test_point_iter(self): ii = iter(self.p) self.assertEqual(1, ii.next()) self.assertEqual(2, ii.next()) self.assertEqual(3, ii.next()) self.assertRaises(StopIteration, ii.next) def test_point_getitem(self): self.assertEqual(self.p[0], 1) self.assertEqual(self.p[1], 2) self.assertEqual(self.p[2], 3)
def test_point_eq(self): pp = Point(self.p.x, self.p.y, self.p.z) self.assertEqual(self.p, pp) self.assertTrue(self.p == pp) self.assertTrue(self.p == (1, 2, 3)) self.assertTrue(self.p == [1, 2, 3])
def setUp(self): self.p = Point(1, 2, 3) self.q = Point(2, 5, 9) self.r = Point(2, 2, 3)
def test_matrix_point_mul(self): self.assertEqual(self.A * self.p, Point(14, 32, 50))
def test_from_tuple(self): self.assertEqual(Point((1, 2, 3)), self.p)
def test_from_list(self): self.assertEqual(Point([1, 2, 3]), self.p)
def last_layer_corners_orientation(self): self.move("X X") # States: 1 2 3 4 5 6 7 8 # B B B B B # BB- -B-B BBB -BB -BB B-B- B-B-B BBB # BBB BBB BBB BBB BBB BBB BBB BBB # -B-B BB- -B- -BB BB-B B-B- B-B-B BBB # B B B B B B def state1(): return ( self.cube[1, 1, 1].colors[1] == self.cube.front_color() and self.cube[-1, -1, 1].colors[1] == self.cube.front_color() and self.cube[1, -1, 1].colors[0] == self.cube.front_color()) def state2(): return ( self.cube[-1, 1, 1].colors[1] == self.cube.front_color() and self.cube[1, 1, 1].colors[0] == self.cube.front_color() and self.cube[1, -1, 1].colors[1] == self.cube.front_color()) def state3(): return ( self.cube[-1, -1, 1].colors[1] == self.cube.front_color() and self.cube[1, -1, 1].colors[1] == self.cube.front_color() and self.cube[-1, 1, 1].colors[2] == self.cube.front_color() and self.cube[1, 1, 1].colors[2] == self.cube.front_color()) def state4(): return ( self.cube[-1, 1, 1].colors[1] == self.cube.front_color() and self.cube[-1, -1, 1].colors[1] == self.cube.front_color() and self.cube[1, 1, 1].colors[2] == self.cube.front_color() and self.cube[1, -1, 1].colors[2] == self.cube.front_color()) def state5(): return (self.cube[-1, 1, 1].colors[1] == self.cube.front_color() and self.cube[1, -1, 1].colors[0] == self.cube.front_color()) def state6(): return ( self.cube[1, 1, 1].colors[1] == self.cube.front_color() and self.cube[1, -1, 1].colors[1] == self.cube.front_color() and self.cube[-1, -1, 1].colors[0] == self.cube.front_color() and self.cube[-1, 1, 1].colors[0] == self.cube.front_color()) def state7(): return ( self.cube[1, 1, 1].colors[0] == self.cube.front_color() and self.cube[1, -1, 1].colors[0] == self.cube.front_color() and self.cube[-1, -1, 1].colors[0] == self.cube.front_color() and self.cube[-1, 1, 1].colors[0] == self.cube.front_color()) def state8(): return ( self.cube[1, 1, 1].colors[2] == self.cube.front_color() and self.cube[1, -1, 1].colors[2] == self.cube.front_color() and self.cube[-1, -1, 1].colors[2] == self.cube.front_color() and self.cube[-1, 1, 1].colors[2] == self.cube.front_color()) move_1 = "Ri Fi R Fi Ri F F R F F " move_2 = "R F Ri F R F F Ri F F " while not state8(): if state1(): self.move(move_1) elif state2(): self.move(move_2) elif state3(): self.move(move_2 + "F F " + move_1) elif state4(): self.move(move_2 + move_1) elif state5(): self.move(move_1 + "F " + move_2) elif state6(): self.move(move_1 + "Fi " + move_1) elif state7(): self.move(move_1 + "F F " + move_1) else: self.move("F") # rotate corners into correct locations (cube is inverted, so swap up and down colors) bru_corner = self.cube.find_piece(self.cube.front_color(), self.cube.right_color(), self.cube.up_color()) while bru_corner.pos != Point(1, 1, 1): self.move("F") self.move("Xi Xi")
def setUp(self): self.p = Point(1, 2, 3) self.q = Point(2, 5, 9) self.r = Point(2, 2, 3)
def test_point_count(self): self.assertEqual(self.r.count(2), 2) self.assertEqual(self.r.count(3), 1) self.assertEqual(self.r.count(5), 0) self.assertEqual(Point(9, 9, 9).count(9), 3)
import string import textwrap from rubik.maths import Point, Matrix RIGHT = X_AXIS = Point(1, 0, 0) LEFT = Point(-1, 0, 0) UP = Y_AXIS = Point(0, 1, 0) DOWN = Point(0, -1, 0) FRONT = Z_AXIS = Point(0, 0, 1) BACK = Point(0, 0, -1) FACE = 'face' EDGE = 'edge' CORNER = 'corner' # 90 degree rotations in the XY plane. CW is clockwise, CC is counter-clockwise. ROT_XY_CW = Matrix(0, 1, 0, -1, 0, 0, 0, 0, 1) ROT_XY_CC = Matrix(0, -1, 0, 1, 0, 0, 0, 0, 1) # 90 degree rotations in the XZ plane (around the y-axis when viewed pointing toward you). ROT_XZ_CW = Matrix(0, 0, -1, 0, 1, 0, 1, 0, 0) ROT_XZ_CC = Matrix(0, 0, 1, 0, 1, 0, -1, 0, 0) # 90 degree rotations in the YZ plane (around the x-axis when viewed pointing toward you). ROT_YZ_CW = Matrix(1, 0, 0, 0, 0, 1, 0, -1, 0) ROT_YZ_CC = Matrix(1, 0, 0, 0, 0, -1, 0, 1, 0) def get_rot_from_face(face): """