Ejemplo n.º 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)
Ejemplo n.º 2
0
 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")
Ejemplo n.º 3
0
def test_CHECKERBOARD_pattern_with_single_twists():
    cube = Cube()

    for turn in CHECKERBOARD_TURNS:
        cube.twist(turn)

    assert cube.cube_string == CHECKERBOARD
Ejemplo n.º 4
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)
Ejemplo n.º 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
Ejemplo n.º 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
Ejemplo n.º 7
0
def test_all_phase1_coordinates_of_cube_in_G1_are_always_0():
    for _ in range(TEST_SIZE):
        cube = Cube()
        cube.scramble_g1()

        assert cube.coordinate_corner_orientation == 0
        assert cube.coordinate_edge_orientation == 0
        assert cube.coordinate_ud_slice == 0
Ejemplo n.º 8
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
Ejemplo n.º 9
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)
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
    def __search(self, phase, notes: List[str], cube: Cube,
                 depth: int) -> Tuple[int, str]:
        """A function to actually perform the search to the current search depth
        by using recursion.

        TODO: Also contains the pruning if the minimum distance increases.

        Return a tuple with the amount of moves as the first item and the
        solution as a notation str as the second item.

        In case a valid solution was not found the amount of moves is negative.
        (currently always -1)"""
        if self.__checked % 10000 == 0:
            print(f"Depth: {depth:2d}, checked: {self.__checked:,}+ " +
                  f"(pruned: {self.__skipped:,}+)",
                  end="\r")
        if depth <= len(notes):
            if phase == 1 and cube.is_domino or cube.is_solved:
                return (len(notes), " ".join(notes))
            return (-1, "")
        for move in Cube.moves if phase == 1 else self.phase2_moves:
            if Cube.skip_move(notes, move):
                self.__skipped += 1
                continue
            new_cube = copy.deepcopy(cube)
            new_cube.twist_by_notation(move)
            self.__checked += 1
            result = self.__search(phase, notes + [move], new_cube, depth)
            if result[0] > 0:
                return result
        return (-1, "")
Ejemplo n.º 12
0
 def __search(self, notes: List[str], cube: Cube, depth: int,
              estimate: int) -> Tuple[int, str]:
     """A function to actually perform the search to the current search depth
     by using recursion. Also contains the pruning if the minimum distance
     increases"""
     if self.__checked % 10000 == 0:
         print(f"Depth: {depth:2d}, checked: {self.__checked:,}+, " +
               f"(pruned: {self.__skipped:,}+)",
               end="\r")
     if len(notes) >= depth or estimate <= 0:
         if cube.is_solved:
             return (len(notes), " ".join(notes))
         return (-1, "")
     for move in cube.moves:
         if Cube.skip_move(notes, move):
             self.__skipped += 1
             continue
         new_cube = copy.deepcopy(cube)
         new_cube.twist_by_notation(move)
         new_estimate = self.__tables.get_distance(self.coordinate(cube))
         if new_estimate != -1:
             if estimate < new_estimate:
                 self.__skipped += 1
                 continue
             estimate = new_estimate + 1
         self.__checked += 1
         result = self.__search(notes + [move], new_cube, depth,
                                estimate - 1)
         if result[0] > 0:
             return result
     return (-1, "")
Ejemplo n.º 13
0
def test_all_coordinates_of_a_solved_cube_are_0():
    cube = Cube()

    assert cube.coordinate_corner_orientation == 0
    assert cube.coordinate_edge_orientation == 0
    assert cube.coordinate_ud_slice == 0
    assert cube.coordinate_corner_permutation == 0
    assert cube.coordinate_edge_permutation == 0
    assert cube.coordinate_ud_slice_phase2 == 0
Ejemplo n.º 14
0
    def generate_tables(self) -> None:
        """A function to generate the pruning tables for Korf's algorithm by
        iterating through search depths from 0 to 20."""
        cube = Cube()

        for depth in range(0, 8):  # FIXME: Should be 0..20 range(0, 21)
            print(f"Generation Depth: {depth}")
            self.generation_search([], cube, depth, 0)
            if self.__tables.is_complete:
                break
            self.__tables.print_completeness()
Ejemplo n.º 15
0
def test_any_cube_with_just_one_move_is_solved():
    for move in Cube.moves:
        cube = Cube()
        cube.twist_by_notation(move)
        result = Simple(cube).solve()
        cube.twist_by_notation(result[1])
        assert cube.is_solved
Ejemplo n.º 16
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
Ejemplo n.º 17
0
def test_a_cube_in_G1_with_4_moves_is_solved():
    cube = Cube()
    cube.twist_by_notation("U R2 B2 D'")

    solution = Kociemba(copy.deepcopy(cube)).solve()
    assert solution[0] > 0 and len(solution[1]) > 0

    cube.twist_by_notation(solution[1])
    assert cube.is_solved
Ejemplo n.º 18
0
def test_checkerboard_is_solved_with_6_moves():
    cube = Cube()
    cube.twist_by_notation("U2 D2 F2 B2 L2 R2")

    solution = Kociemba(copy.deepcopy(cube)).solve()
    assert solution[0] == 6

    cube.twist_by_notation(solution[1])
    assert cube.is_solved
Ejemplo n.º 19
0
    def edge_pattern_second(cls, cube: Cube) -> int:
        """A function to calculate the edge pattern index for the last six
        edges of a cube for Korf's algorithm.

        The pattern is a combination of the orientation (0..63) and the
        permutation (0..665,219) of the last six edges of the cube. Which
        means that the value of index of the pattern is always between 0 and
        42,577,919."""
        order = Cube().edge_order[6:][::-1]
        edges = [
            edge if edge in order or edge[::-1] in order else "-"
            for edge in cube.unoriented_edges
        ][::-1]

        return cls.__edge_pattern(order, edges)
Ejemplo n.º 20
0
def test_cubes_in_G1_with_4_random_moves_are_solved():
    for _ in range(5):
        cube = Cube()
        cube.scramble_g1(4)

        solution = Kociemba(copy.deepcopy(cube)).solve()
        assert solution[0] >= 0 and len(solution[1]) >= 0

        cube.twist_by_notation(solution[1])
        assert cube.is_solved
Ejemplo n.º 21
0
def test_all_cubes_with_one_move_are_solved():
    for move in Cube.moves:
        cube = Cube()
        cube.twist_by_notation(move)

        solution = Kociemba(copy.deepcopy(cube)).solve()
        assert solution[0] >= 1

        cube.twist_by_notation(solution[1])
        assert cube.is_solved
Ejemplo n.º 22
0
    def generation_search(self, notes: List[str], cube: Cube, depth: int,
                          distance: int) -> None:
        """A function to search all of the patterns indexes to generate the
        pruning tables required by the Korf's algorithm to solve any cube in
        less than about 10^12 years.

        Unfortunately this function currently takes about 10^13 years with depth
        20 to finish on a modern desktop computer."""
        # FIXME: Optimize to run in less than a week.
        # FIXME: Pruning while generating doesn't seem to work correctly.
        if distance >= depth:
            self.__tables.set_distance(self.coordinate(cube), distance)
            return
        for move in cube.moves:
            if Cube.skip_move(notes, move):
                continue
            new_cube = copy.deepcopy(cube)
            new_cube.twist_by_notation(move)
            estimate = self.__tables.get_distance(self.coordinate(new_cube))
            if estimate != -1 and estimate - depth < distance:
                # print(f"Depth: {depth}, distance: {distance}, move: {move}")
                continue
            self.generation_search(notes + [move], new_cube, depth,
                                   distance + 1)
Ejemplo n.º 23
0
def test_solved_cube_is_domino():
    assert Cube().is_domino
Ejemplo n.º 24
0
def test_the_str_of_a_solved_cube_is_correct():
    assert str(Cube()) == SOLVED_STR
Ejemplo n.º 25
0
def test_CUBE_IN_THE_CUBE_pattern():
    cube = Cube()
    cube.twist_by_notation(CUBE_IN_THE_CUBE_NOTATION)

    assert cube.cube_string == CUBE_IN_THE_CUBE
Ejemplo n.º 26
0
def test_CHECKERBOARD_is_domino():
    cube = Cube()
    cube.twist_by_notation(CHECKERBOARD_NOTATION)

    assert cube.is_domino
Ejemplo n.º 27
0
def test_empty_notation_doesnt_affect_the_cube():
    cube = Cube()
    cube.twist_by_notation("")

    assert cube.is_solved
Ejemplo n.º 28
0
def test_cube_string_of_a_solved_cube_is_correct():
    SOLVED_STRing = "UUUUUUUUULLLLLLLLLFFFFFFFFFRRRRRRRRRBBBBBBBBBDDDDDDDDD"
    cube_string = Cube().cube_string

    assert SOLVED_STRing == cube_string
Ejemplo n.º 29
0
def test_random_cubes_in_G1_are_domino():
    for _ in range(5):
        cube = Cube()
        cube.scramble_g1()
        assert cube.is_domino
Ejemplo n.º 30
0
def test_CUBE_IN_THE_CUBE_is_not_domino():
    cube = Cube()
    cube.twist_by_notation(CUBE_IN_THE_CUBE_NOTATION)

    assert not cube.is_domino