Example #1
0
def test_triple_is_never_0_for_an_unsolved_cube():
    for _ in range(TEST_SIZE):
        cube = Cube()
        while cube.is_solved:
            cube.scramble()

        assert cube.triple != (0, 0, 0)
Example #2
0
def test_triple_is_never_0_for_a_cube_not_in_G1():
    for _ in range(TEST_SIZE):
        cube = Cube()
        while cube.is_domino:
            cube.scramble()

        assert cube.triple != (0, 0, 0)
Example #3
0
def test_any_random_cube_is_solved():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble()
        result = Simple(cube).solve()
        cube.twist_by_notation(result[1])
        assert cube.is_solved
Example #4
0
def test_cube_is_solved_after_reset():
    cube = Cube()
    cube.scramble()
    cube.twist(2)
    cube.twist_by_notation("U2 B D'")
    cube.reset()

    assert cube.is_solved
Example #5
0
def test_random_scramble_has_one_of_each_edge():
    for _ in range(10):
        cube = Cube()
        cube.scramble()
        edges = cube.edges

        for edge in Cube.edge_order:
            assert edge in edges
Example #6
0
def test_random_scramble_has_one_of_each_corner():
    for _ in range(10):
        cube = Cube()
        cube.scramble()
        corners = cube.corners

        for corner in Cube.corner_order:
            assert corner in corners
Example #7
0
def test_all_phase1_coordinates_of_cube_not_in_G1_are_never_0():
    for _ in range(TEST_SIZE):
        cube = Cube()
        while cube.is_domino:
            cube.scramble()

        x1 = cube.coordinate_corner_orientation
        x2 = cube.coordinate_edge_orientation
        x3 = cube.coordinate_ud_slice

        assert (x1, x2, x3) != (0, 0, 0)
Example #8
0
def test_all_coordinates_of_a_not_solved_cube_are_never_0():
    for _ in range(TEST_SIZE):
        cube = Cube()
        while cube.is_solved:
            cube.scramble()

        x1 = cube.coordinate_corner_orientation
        x2 = cube.coordinate_edge_orientation
        x3 = cube.coordinate_ud_slice
        x4 = cube.coordinate_corner_permutation
        x5 = cube.coordinate_edge_permutation
        x6 = cube.coordinate_ud_slice_phase2

        assert (x1, x2, x3, x4, x5, x6) != (0, 0, 0, 0, 0, 0)
Example #9
0
def test_coordinate_ud_slice_is_always_between_0_and_494():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble()

        assert 0 <= cube.coordinate_ud_slice <= 494
Example #10
0
def test_a_scrambled_cube_is_not_solved():
    cube = Cube()
    cube.scramble()

    assert not cube.is_solved
Example #11
0
def test_coordinate_edge_orientation_is_always_between_0_and_2047():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble()

        assert 0 <= cube.coordinate_edge_orientation <= 2047
Example #12
0
def test_random_scramble_has_all_corners():
    for _ in range(10):
        cube = Cube()
        cube.scramble()

        assert None not in cube.corners
Example #13
0
def test_edge_pattern_second_is_always_in_the_correct_range():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble()

        assert 0 <= Korf.edge_pattern_second(cube) <= 42_577_919
Example #14
0
def test_corner_patter_is_always_in_the_correct_range():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble()

        assert 0 <= Korf.corner_pattern(cube) <= 88_179_839
Example #15
0
class CubeSolver:
    """A class providing the UI of the CubeSolver application.

    The method check_notation can be used to check if a string of simple cube
    notations is valid. And the UI itself can be started by running the method
    start."""
    def __init__(self):
        print("Initializing...", end="", flush=True)
        self.__cube = Cube()
        self.__simple = Simple(self.__cube)
        self.__kociemba = Kociemba(self.__cube)
        self.__korf = Korf(self.__cube)
        print(" Done.\n")

    def __choose_method(self):
        print("\nAvailable solving methods:")
        print("0 - Simple method (fast, a lot of moves)")
        print("1 - Kociemba's algorithm (slower, fewer moves")
        print("2 - Korf's algorithm (slowest, fewest moves")
        print("(r or q - return to the main menu)")

        while True:
            method = input("\nMethod: ")

            if method in ["r", "q"]:
                print()
                break

            start_time = time.time()
            solution = (-1, "")
            if method == "0":
                self.__simple.set_cube(self.__cube)
                solution = self.__simple.solve()
            elif method == "1":
                self.__kociemba.set_cube(self.__cube)
                solution = self.__kociemba.solve()
            elif method == "2":
                print()
                self.__korf.set_cube(self.__cube)
                solution = self.__korf.solve()
            else:
                print("Invalid option")
                return
            total_time = time.time() - start_time
            if solution[0] < 0:
                print(f"\nCouldn't find a solution in {total_time:.3f}" +
                      " seconds.")
            else:
                print(f"\nFound solution: {solution[1]} with {solution[0]} " +
                      f"turns in {total_time:.3f} seconds.")

    def __play(self):
        print("\nMoves should be given with the basic cube notation.")
        print("r or q will return to the main menu.\n")
        print(f"{self.__cube}\n")
        while True:
            notation = input("Next move(s): ").strip()
            if notation in ["r", "q"]:
                print()
                break

            if self.check_notation(notation):
                self.__cube.twist_by_notation(notation)
            else:
                print("Invalid notation!")

            print(f"\n{self.__cube}\n")

    @staticmethod
    def check_notation(notation: str) -> bool:
        """A function to check the validity of a string containing cube
        notation.

        For example the notation 'F2 B2 L2 R2 D2 U2' is valid but 'U3', 'U-1',
        'M', 'X', 'Y', or 'Z' are not valid."""
        if len(notation) == 0:
            return False
        for note in notation.split(" "):
            if note[0] not in ["U", "R", "F", "L", "B", "D"]:
                return False
            if len(note) > 2:
                return False
            if len(note) == 2 and note[1] not in ["'", "2"]:
                return False
        return True

    @staticmethod
    def __list_commands() -> None:
        print("Available commands:")
        print("0 - scramble (or 'g' for scramble in <U,D,L2,R2,F2,B2>")
        print("1 - solve")
        print("2 - play")
        print("3 - reset")
        print("q - quit")

    def start(self) -> None:
        """A function containing the main loop for the programs UI."""
        while True:
            print(f"{self.__cube}\n")
            self.__list_commands()

            command = input("\nCommand: ").lower()

            if command == 'q':
                break
            if command == '0':
                scramble = self.__cube.scramble()
                print(f"\nScramble: {scramble}\n")
            elif command == 'g':
                scramble = self.__cube.scramble_g1()
                print(f"\nScramble: {scramble}\n")
            elif command == '1':
                self.__choose_method()
            elif command == '2':
                self.__play()
            elif command == '3':
                print()
                self.__cube.reset()
            else:
                print("\nInvalid command!\n")