def __init__(self, cube): ''' Initialize the solver. Arguments: cube -- cube to be solved Attributes: face_order -- list denoting the order used to create and read string representations of cubes throughout the program moves -- dictionary linking the cube moves that will be used throughout the program to the associated inputs to the cube move_slice method and the inverse move scrambles -- dictionary linking cube states from the scrambled state to moves lists for reaching said states solves -- dictionary linking cube states from the solved state to moves lists for reaching said states ''' solved = r.RubiksCube(2) while solved.rep.get_row('F', 0)[1] != cube.rep.get_row('F', 0)[1] or \ solved.rep.get_row('U', 1)[1] != cube.rep.get_row('U', 1)[1] or \ solved.rep.get_row('R', 0)[0] != cube.rep.get_row('R', 0)[0]: solved.random_rotations(1) self.face_order = ['U', 'D', 'L', 'R', 'F', 'B'] self.moves = { "l": ['L', 0, "l'"], "l'": ['R', 1, "l"], "d": ['D', 0, "d'"], "d'": ['U', 1, "d"], "b": ['B', 0, "b'"], "b'": ['F', 1, "b"] } self.scrambles = {self.get_rep(cube): ''} self.solves = {self.get_rep(solved): ''}
def match_corners(): ''' Solves the corners relative to each other, not including centers. ''' cube = r.RubiksCube(2) for face in cube.rep.contents: row_0 = self.control.cube.rep.get_row(face, 0) row_2 = self.control.cube.rep.get_row(face, 2) cube.rep.set_row(face, 0, [row_0[0], row_0[2]]) cube.rep.set_row(face, 1, [row_2[0], row_2[2]]) sub_solver = Solver_2x2(cube) for cmd in sub_solver.solve(): self.move(cmd)
def test_face_str(self): """ Test that it correctly outputs a single face as a string """ rubix = rubiks_cube.RubiksCube() orange_face = rubix.get_face_str('Orange') target_str = """ _ _ _ |O|O|O| |O|O|O| |O|O|O| ¯ ¯ ¯ """ # noqa W291 self.assertEqual(orange_face, target_str)
def get_cube(self, str_rep): ''' Generates a cube with the scramble specified by a string representation. Arguments: str_rep -- string representation of a cube Return -- cube with scramble represented by str_rep ''' cube = r.RubiksCube(2) index = 0 for face in self.face_order: cube.rep.set_row(face, 0, [str_rep[index], str_rep[index + 1]]) cube.rep.set_row(face, 1, [str_rep[index + 2], str_rep[index + 3]]) index += 4 return cube
def __init__(self, cubeSize, numMoves, mode): self.cubeSize = cubeSize self.numMoves = numMoves # 0 - Manual gameplay # 1 - Tree AI # 2 - Baseline (Random) AI # TODO: Rework this listing. self.mode = mode # Window width/height in pixels. self.winWidth = 600 self.winHeight = 600 # Using: self.programmedMoves = ['0Y270', '1Z180', '2X180', '2Z180', '1X270', '2Y180', '2Z270'] # 3//64, 4//88, 5//112 showed good performance. self.programmedMoves = [] self.programmedCosts = np.array([], dtype=int) #self.programmedMoves = ['1X270', '0X90', '1X90'] #self.programmedMoves = ['1X270', '1Y90', '0X180'] #self.programmedMoves = ['0Y270', '1Z180', '2X180', '2Z180', '1X270', '2Y180', '2Z270'] #self.neighborFactor = 5 #self.depthReductionFactor = 112 self.solveLimit = math.inf self.metaSolve = 0 self.diagnostics = 0 # The current state of the game. self.cube = rubiks_cube.RubiksCube(cubeSize) if len(self.programmedMoves) == 0: actualMoves_actualCosts = self.cube.generateCube(numMoves) self.actualMoves = actualMoves_actualCosts[0] self.actualCosts = actualMoves_actualCosts[1] else: self.cube.loadCube(self.programmedMoves, self.programmedCosts) self.actualMoves = self.programmedMoves self.actualCosts = self.programmedCosts print("Actual moves: \n" + str(self.actualMoves)) self.tree = rubiks_tree.RubiksTree(self.cube) # The remaining moves to complete the game, as solved by the AI. self.moves = [] self.optimalCost = math.inf
def do_solve(self, filename): ''' Saves the output of the solution to a rubiks cube to a file. ''' with open(filename, 'w') as outfile: if self.cube.rep.size == 2: solver = s.Solver_2x2(self.cube) else: solver = s.Solver_3x3(self.cube) solution = solver.solve() c_cube = c.RubiksCube(self.cube.rep.size) c_cube.rep.set_contents(self.cube.rep.get_contents()) control = RubiksControl(self.cube.rep.size) control.cube = c_cube print('Initial state:', file=outfile) print(control.cube.display(), file=outfile) for cmd in solution: control.do_command(cmd) print(cmd, file=outfile) print(control.cube.display(), file=outfile) print('Solution length (qt): ' + str(c_cube.count), file=outfile)
def test_str_ouput(self): """ Test that an unmodified cube outputs the correct str representation """ rubix_str = str(rubiks_cube.RubiksCube()) target_str = """ _ _ _ |G|G|G| |G|G|G| |G|G|G| ¯ ¯ ¯ _ _ _ _ _ _ _ _ _ _ _ _ |Y|Y|Y| |R|R|R| |W|W|W| |O|O|O| |Y|Y|Y| |R|R|R| |W|W|W| |O|O|O| |Y|Y|Y| |R|R|R| |W|W|W| |O|O|O| ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ ¯ _ _ _ |B|B|B| |B|B|B| |B|B|B| ¯ ¯ ¯ """ # noqa W291 self.assertEqual(rubix_str, target_str)
def test_do_command(): for size in [2, 3]: control = c.RubiksControl(size) cube = cc.RubiksCube(size) # Use test data, as usual. control.cube.rep.test_faces() cube.rep.test_faces() control.do_command('f') cube.move_face('F', '+') assert control.cube.rep.contents == cube.rep.contents control.do_command("u'") cube.move_face('U', '-') assert control.cube.rep.contents == cube.rep.contents control.do_command('fur') # == f u r u' r' f' cube.move_face('F', '+') cube.move_face('U', '+') cube.move_face('R', '+') cube.move_face('U', '-') cube.move_face('R', '-') cube.move_face('F', '-') assert control.cube.rep.contents == cube.rep.contents # Check that bogus moves raise a BadCommand exception. try: control.do_command('foobarbazbam') print('ERROR: a BadCommand exception should have been raised') assert False except c.BadCommand: pass except: print('ERROR: a BadCommand exception should have been raised ', end='') print(' but a different exception was raised instead.') assert False
def __init__(self, size, scramble=True): ''' Initialize the cube representation. Initialize the set of basic commands. Arguments: size -- the size of the cube (must be > 1) -- 2 means a 2x2x2 cube; 3 means a 3x3x3 cube; etc scramble -- True if you want the cube scrambled ''' assert size in [2, 3] self.cube = c.RubiksCube(size) self.history = [] if scramble: self.cube.scramble() # Built-in commands. # Use lower-case for ease of typing. # Use double quotes since some commands use the single quote character. self.face_moves = \ ["u", "u'", "d", "d'", "f", "f'", "b", "b'", "l", "l'", "r", "r'"] self.rotations = ["x", "x'", "y", "y'", "z", "z'"] self.user_commands = copy.deepcopy(u.user_commands)
permutations.append(permutation) if depth > 0: for i in range(len(list)): permute(list, permutation + [list[i]], permutations, \ depth - 1) permutations = [] permute(list, [], permutations, depth) permutations.sort(key=len) return permutations orig_contents = self.control.cube.rep.get_contents() orig_moves = self.moves[:] for permutation in permutations(moves, depth): self.move(permutation) is_pref = condition() if is_pref: return True else: self.control.cube.rep.set_contents(orig_contents) while self.moves != orig_moves: self.moves.pop(len(self.moves) - 1) return False if __name__ == '__main__': cube = r.RubiksCube(3) cube.scramble() solver = Solver_3x3(cube) solver.solve()
def test_is_solved(): # Test that solved cubes are solved :) cube = c.RubiksCube(2) assert cube.is_solved() cube = c.RubiksCube(3) assert cube.is_solved() # Test that scrambled cubes are not solved. # There is a vanishingly small probability that this test will fail # due to a scramble which does nothing. cube = c.RubiksCube(2) cube.scramble() assert not cube.is_solved() cube = c.RubiksCube(3) cube.scramble() assert not cube.is_solved() # Test that cubes containing only one color are not solved. face_contents2 = [['w', 'w'], ['w', 'w']] rep2 = {} for face in 'UDFBLR': rep2[face] = copy.deepcopy(face_contents2) cube = c.RubiksCube(2) cube.rep.contents = rep2 try: cube.is_solved() assert False # should never reach here! except c.InvalidCube as e: pass except: # all other exceptions are mistakes. print('Expecting InvalidCube exception') assert False face_contents3 = [['w', 'w', 'w'], ['w', 'w', 'w'], ['w', 'w', 'w']] rep3 = {} for face in 'UDFBLR': rep3[face] = copy.deepcopy(face_contents3) cube = c.RubiksCube(3) cube.rep.contents = rep3 try: cube.is_solved() assert False # should never reach here! except c.InvalidCube as e: pass except: # all other exceptions are mistakes. print('Expecting InvalidCube exception') assert False # Test that cubes containing all the one-color faces # in an invalid orientation are not solved. for size in [2, 3]: cube = c.RubiksCube(size) contents = cube.rep.contents (U, F) = (contents['U'], contents['F']) contents['U'] = F contents['F'] = U cube.rep.contents = contents try: cube.is_solved() assert False # should never reach here! except c.InvalidCube as e: pass except: # all other exceptions are mistakes. print('Expecting InvalidCube exception') assert False for size in [2, 3]: cube = c.RubiksCube(size) contents = cube.rep.contents (U, D) = (contents['U'], contents['D']) contents['U'] = D contents['D'] = U cube.rep.contents = contents try: cube.is_solved() assert False # should never reach here! except c.InvalidCube as e: pass except: # all other exceptions are mistakes. print('Expecting InvalidCube exception') assert False
def test_move_face(): # # Size = 2 # cube = c.RubiksCube(2) cube.rep.test_faces() contents = copy.deepcopy(cube.rep.contents) assert cube.rep.contents == cube2_orig count = cube.count cube.move_face('U', '+') assert cube.rep.contents == cube2_u_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('U', '-') assert cube.rep.contents == cube2_u_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('D', '+') assert cube.rep.contents == cube2_d_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('D', '-') assert cube.rep.contents == cube2_d_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('F', '+') assert cube.rep.contents == cube2_f_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('F', '-') assert cube.rep.contents == cube2_f_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('B', '+') assert cube.rep.contents == cube2_b_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('B', '-') assert cube.rep.contents == cube2_b_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('L', '+') assert cube.rep.contents == cube2_l_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('L', '-') assert cube.rep.contents == cube2_l_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('R', '+') assert cube.rep.contents == cube2_r_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('R', '-') assert cube.rep.contents == cube2_r_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) # # Size = 3 # cube = c.RubiksCube(3) cube.rep.test_faces() contents = copy.deepcopy(cube.rep.contents) assert cube.rep.contents == cube3_orig count = cube.count cube.move_face('U', '+') assert cube.rep.contents == cube3_u_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('U', '-') assert cube.rep.contents == cube3_u_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('D', '+') assert cube.rep.contents == cube3_d_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('D', '-') assert cube.rep.contents == cube3_d_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('F', '+') assert cube.rep.contents == cube3_f_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('F', '-') assert cube.rep.contents == cube3_f_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('B', '+') assert cube.rep.contents == cube3_b_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('B', '-') assert cube.rep.contents == cube3_b_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('L', '+') assert cube.rep.contents == cube3_l_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('L', '-') assert cube.rep.contents == cube3_l_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('R', '+') assert cube.rep.contents == cube3_r_plus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.move_face('R', '-') assert cube.rep.contents == cube3_r_minus assert cube.count == count + 1 cube.rep.contents = copy.deepcopy(contents)
def test_rotate_cube(): # # Size = 2 # cube = c.RubiksCube(2) cube.rep.test_faces() contents = copy.deepcopy(cube.rep.contents) assert cube.rep.contents == cube2_orig count = cube.count cube.rotate_cube('X', '+') assert cube.rep.contents == cube2_x_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('X', '-') assert cube.rep.contents == cube2_x_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Y', '+') assert cube.rep.contents == cube2_y_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Y', '-') assert cube.rep.contents == cube2_y_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Z', '+') assert cube.rep.contents == cube2_z_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Z', '-') assert cube.rep.contents == cube2_z_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) # # Size = 3 # cube = c.RubiksCube(3) cube.rep.test_faces() contents = copy.deepcopy(cube.rep.contents) assert cube.rep.contents == cube3_orig count = cube.count cube.rotate_cube('X', '+') assert cube.rep.contents == cube3_x_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('X', '-') assert cube.rep.contents == cube3_x_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Y', '+') assert cube.rep.contents == cube3_y_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Y', '-') assert cube.rep.contents == cube3_y_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Z', '+') assert cube.rep.contents == cube3_z_plus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents) count = cube.count cube.rotate_cube('Z', '-') assert cube.rep.contents == cube3_z_minus assert cube.count == count # no change cube.rep.contents = copy.deepcopy(contents)