예제 #1
0
def yellow_corners(state_str):
    side_faces = ["F", "R", "B", "L"]
    aim_corners = [{"D", side_faces[i], side_faces[(i + 1) % 4]}
                   for i in range(4)]
    corners = []
    for f in side_faces:
        n = get_normal(f)
        m = np.cross(Y, n)
        pos = -Y + n + m
        corners.append({
            get_color_from_state_str(state_str, pos, -Y),
            get_color_from_state_str(state_str, pos, n),
            get_color_from_state_str(state_str, pos, m)
        })
    is_rightly_positioned = [c == cc for c, cc in zip(aim_corners, corners)]
    if sum(is_rightly_positioned) == 1:
        i = is_rightly_positioned.index(True)  # Belgium
        # print("One belgium found", i)
        to_right = aim_corners[(i + 1) % 4] == corners[(i + 3) % 4]
        # print(f"{to_right=}")
        moves = BELGIUM if not to_right else flip_left_right(BELGIUM)
        return rotate_moves_about_y(moves,
                                    get_normal(side_faces[(i + to_right) % 4]))
    # print("Not belgium found")
    return BELGIUM
예제 #2
0
def orient_yellow_corners(state_str):
    normals = (Z, X, -Z, -X)
    # Look for two consecutive misoriented corners
    for i, n in enumerate(normals):
        m = np.cross(Y, n)  # Right
        pos = -Y + n + m
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if c_down != "D":
            # print(f"Corner wrongly oriented {i} - {c_down}")
            if get_color_from_state_str(state_str, pos - 2 * n, -Y) != "D":
                # print("Next corner also misoriented")
                if c_down == get_face_for_normal(m):
                    # print("Moving corners down")
                    return rotate_moves_about_y(FLIPPED_DOUBLE_CHAIR, n)
                else:
                    # print("Moving corners up")
                    return rotate_moves_about_y(DOUBLE_CHAIR, n)
    # Else only two diagonal misoriented corners
    for i, n in enumerate(normals):
        m = np.cross(Y, n)  # Right
        pos = -Y + n + m
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if c_down != "D":
            # print("Diagonal")
            moves = FLIPPED_DOUBLE_CHAIR if c_down == get_face_for_normal(
                m) else DOUBLE_CHAIR
            return [neg_move(get_face_for_normal(m))] + rotate_moves_about_y(
                moves, m) + [get_face_for_normal(m)]
    raise ValueError("No misoriented corner: is cube done?")
예제 #3
0
def is_yellow_cross_oriented(state_str):
    for n in (X, -X, Z, -Z):
        pos = np.array([0, -1, 0]) + n
        c_down = get_color_from_state_str(state_str, pos, -Y)
        c_side = get_color_from_state_str(state_str, pos, n)
        if c_down != "D" or get_face_for_normal(n) != c_side:
            return False
    return True
예제 #4
0
def white_cross(state_str):
    # Start with 2nd crown edges
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 0, z])
            cols = [
                get_color_from_state_str(state_str, pos, x * X),
                get_color_from_state_str(state_str, pos, z * Z)
            ]
            if "U" in cols:
                # print("2nd crown")
                i = [c != "U" for c in cols].index(True)
                col = cols[i]
                n = [x * X, z * Z][i]
                v = get_normal(col)
                # print(n, v)
                u = [x * X, z * Z][1 - i]

                m1, m3 = _get_up_turn(n, v)

                m2 = get_face_for_normal(n)
                if np.cross(n, u)[1] > 0:
                    m2 += "'"
                # print(m1, m2, m3)

                return m1 + [m2] + m3

    # Then down edges
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, -1, z])
        c_side = get_color_from_state_str(state_str, pos, n)
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if c_down == "U":
            # print("Down - down")
            m1, m3 = _get_up_turn(get_normal(c_side), n)
            m2 = get_face_for_normal(n) + "2"
            # print(m1, m2, m3)
            return m1 + [m2] + m3
        elif c_side == "U":
            # print("Down - side")
            m1, m3 = _get_up_turn(get_normal(c_side), n)
            m = get_face_for_normal(n)
            mm = get_face_for_normal(np.cross(n, Y))
            m2 = [m, "U", mm, "U'"]

            return m1 + m2 + m3

    # Then up edges (if misplaced)
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, 1, z])
        # print(pos, get_color_from_state_str(state_str, pos, n))
        if get_color_from_state_str(state_str, pos,
                                    n) != get_face_for_normal(n):
            # print("Misplaced", pos, n)
            return [get_face_for_normal(n)]  # Simply get it out

    raise ValueError("No move found, it cross done?")
예제 #5
0
def is_second_crown_done(state_str):
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 0, z])
            cx = get_color_from_state_str(state_str, pos, x * X)
            cz = get_color_from_state_str(state_str, pos, z * Z)
            if cx != get_face_for_normal(x * X) or cz != get_face_for_normal(
                    z * Z):
                return False
    return True
예제 #6
0
def is_white_corners_done(state_str):
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 1, z])
            cu = get_color_from_state_str(state_str, pos, Y)
            cx = get_color_from_state_str(state_str, pos, x * X)
            cz = get_color_from_state_str(state_str, pos, z * Z)
            if cu != "U" or cx != get_face_for_normal(
                    x * X) or cz != get_face_for_normal(z * Z):
                return False
    return True
예제 #7
0
def is_white_cross_done(state_str):
    for x in (-1, 1):
        pos = np.array([x, 1, 0])
        # print(pos, get_color_from_state_str(state_str, pos, Y), get_color_from_state_str(state_str, pos, x * X), get_face_for_normal(x * X))
        if get_color_from_state_str(state_str, pos, Y) != "U" or \
                get_color_from_state_str(state_str, pos, x * X) != get_face_for_normal(x * X):
            return False
    for z in (-1, 1):
        pos = np.array([0, 1, z])
        if get_color_from_state_str(state_str, pos, Y) != "U" or \
                get_color_from_state_str(state_str, pos, z * Z) != get_face_for_normal(z * Z):
            return False
    return True
예제 #8
0
def is_yellow_corners_positioned(state_str):
    side_faces = ["F", "R", "B", "L"]
    for i, f in enumerate(side_faces):
        n = get_normal(f)
        m = np.cross(Y, n)
        pos = -Y + n + m
        corner = {
            get_color_from_state_str(state_str, pos, -Y),
            get_color_from_state_str(state_str, pos, n),
            get_color_from_state_str(state_str, pos, m)
        }
        aim_corner = {"D", side_faces[i], side_faces[(i + 1) % 4]}
        if aim_corner != corner:
            return False
    return True
예제 #9
0
def is_yellow_cross_done(state_str):
    for n in (X, -X, Z, -Z):
        pos = np.array([0, -1, 0]) + n
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if c_down != "D":
            return False
    return True
예제 #10
0
def orient_yellow_cross(state_str):
    ALL_DIRECTIONS = [X, -Z, -X, Z]
    # Check if just one color already aligned
    colors = [
        get_color_from_state_str(state_str, -Y + n, n) for n in ALL_DIRECTIONS
    ]
    aim_colors = [get_face_for_normal(n) for n in ALL_DIRECTIONS]
    is_rightly_positioned = [c == cc for c, cc in zip(colors, aim_colors)]
    if sum(is_rightly_positioned) == 1:
        # print("One is right")
        i = is_rightly_positioned.index(True)
        to_right = colors[(i + 1) % 4] == aim_colors[(i + 3) % 4]
        moves = CHAIR if not to_right else flip_left_right(CHAIR)
        # print(to_right)
        return rotate_moves_about_y(moves, ALL_DIRECTIONS[i])

    # Else try to rotate Up
    for shift in range(4):
        is_rightly_positioned = [
            c == cc for c, cc in zip(rotate_list(colors, shift), aim_colors)
        ]
        if sum(is_rightly_positioned) == 1:
            # print(f"Turn down {shift} times")
            # Just turn they go back to start of function
            return ["D"] * shift
    # Else run CHAIR
    return CHAIR
예제 #11
0
def white_corners(state_str):
    # Down corners
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, -1, z])
            csx = get_color_from_state_str(state_str, pos, x * X)
            csz = get_color_from_state_str(state_str, pos, z * Z)
            c_down = get_color_from_state_str(state_str, pos, -Y)
            if csx == "U" or csz == "U":
                # White on side
                # print("Down - side", csx, csz, c_down)
                n = x * X if csx == "U" else z * Z
                v = z * Z if csx == "U" else x * X
                col = csz if csx == "U" else csx
                m1, m3 = _get_up_turn(get_normal(col), v)
                to_right = np.cross(v, n)[1] > 0
                m2 = [get_face_for_normal(n), "D"]
                if to_right:
                    m2[0] += "'"
                    m2[1] += "'"
                m2.append(neg_move(m2[0]))
                return m1 + m2 + m3
            elif c_down == "U":
                # White down -> just move it on side
                csx = get_color_from_state_str(state_str, pos, x * X)
                csz = get_color_from_state_str(state_str, pos, z * Z)
                # print("Down - down", csx, csz)
                m1, m3 = _get_up_turn(get_normal(csx),
                                      z * Z)  # Rotate around x
                f = get_face_for_normal(x * X)
                m2 = [f, "D'", neg_move(f)]
                if x * z > 0:
                    m2 = [neg_move(m) for m in m2]
                # print(m1 + m2 + m3)
                return m1 + m2 + m3
    # Up corners -> move it down
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 1, z])
            cu = get_color_from_state_str(state_str, pos, Y)
            csx = get_color_from_state_str(state_str, pos, x * X)
            csz = get_color_from_state_str(state_str, pos, z * Z)
            if cu != "U" or csx != get_face_for_normal(
                    x * X) or csz != get_face_for_normal(z * Z):
                # print("Corner wrongly oriented")
                n = x * X if csx == "U" else z * Z
                v = z * Z if csx == "U" else x * X
                m2 = [
                    get_face_for_normal(n), "D",
                    neg_move(get_face_for_normal(n))
                ]
                to_right = np.cross(v, n)[1] > 0
                if to_right:
                    m2 = [neg_move(m) for m in m2]
                return m2
    raise ValueError("No move found: is white face finished?")
예제 #12
0
def second_crown(state_str):
    for x, z, n in [(-1, 0, -X), (1, 0, X), (0, -1, -Z), (0, 1, Z)]:
        pos = np.array([x, -1, z])
        c_side = get_color_from_state_str(state_str, pos, n)
        c_down = get_color_from_state_str(state_str, pos, -Y)
        if "D" not in [c_side, c_down]:  # Down edges
            # print("Down edge", c_down, c_side)
            # Move in front of c_side color
            theta = angle(n, get_normal(c_side), ignore_axis=1)
            theta = (np.round(theta / np.pi * 2) * 90) % 360
            m1 = []
            if theta == 90:
                m1 = ["D'"]
            elif theta == 180:
                m1 = ["D2"]
            if theta == 270:
                m1 = ["D"]
            # is_right if c_down is to its right
            to_left = np.cross(get_normal(c_side), get_normal(c_down))[1] > 0
            moves = BASE_SECOND_CROWN_MOVE
            if not to_left:
                # print("to_right")
                moves = flip_left_right(moves)
            moves = rotate_moves_about_y(moves, get_normal(c_side))
            return m1 + moves
    for x in (-1, 1):
        for z in (-1, 1):
            pos = np.array([x, 0, z])
            cs1 = get_color_from_state_str(state_str, pos, x * X)
            cs2 = get_color_from_state_str(state_str, pos, z * Z)
            if cs1 != get_face_for_normal(x * X) or cs2 != get_face_for_normal(
                    z * Z):  # Wrong place / orientation
                # print("Edge misplaced", cs1, cs2, x, z)
                if x * z == -1:
                    rotate_about = x * X
                else:
                    rotate_about = z * Z
                moves = rotate_moves_about_y(BASE_SECOND_CROWN_MOVE,
                                             rotate_about)
                return moves
    raise ValueError("No edge for second crown, is second crown done?")
예제 #13
0
def test_get_color_from_state_str():
    state = "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB"
    for x in (-1, 0, 1):
        for y in (-1, 0, 1):
            for z in (-1, 0, 1):
                if x == y == z == 0:
                    continue
                pos = np.array([x, y, z])
                for n in (x * X, y * Y, z * Z):
                    if np.linalg.norm(n) != 0:
                        assert get_color_from_state_str(
                            state, pos, n) == get_face_for_normal(n)
예제 #14
0
def yellow_cross(state_str):
    posx = -Y + X
    posmx = -Y - X
    posz = -Y + Z
    posmz = -Y - Z
    col_x = get_color_from_state_str(state_str, posx, -Y)
    col_mx = get_color_from_state_str(state_str, posmx, -Y)
    col_z = get_color_from_state_str(state_str, posz, -Y)
    col_mz = get_color_from_state_str(state_str, posmz, -Y)
    if "D" not in [col_x, col_mx, col_z, col_mz]:
        # print("No yellow")
        return BASE_YELLOW_CROSS
    elif col_x == col_mx == "D":
        # print("Line along X")
        return rotate_moves_about_y(BASE_YELLOW_CROSS, X)
    elif col_z == col_mz == "D":
        # print("Line along Z")
        return BASE_YELLOW_CROSS
    else:
        # print("Yellow corner")
        corner = (col_x == "D") * X + (col_mx == "D") * (-X) + (
            col_z == "D") * Z + (col_mz == "D") * (-Z)
        n = Rotation.from_rotvec(Y * np.pi * 3 / 8).apply(corner)
        return rotate_moves_about_y(BASE_YELLOW_CROSS2, -n)
예제 #15
0
def generate_cubes_from_state_str(state_str, check=False):
    if check:
        try:
            kociemba.solve(state_str)
        except ValueError as e:
            raise ValueError(f"Invalid state string {state_str}")

    base = np.eye(3)
    cubes = [None] * 26
    i = 0
    for x in (-1, 0, 1):
        for y in (-1, 0, 1):
            for z in (-1, 0, 1):
                if x == y == z == 0:  # Skip center cube
                    continue
                pos = np.array([x, y, z])

                colors = [False] * 6
                basis = [None] * 3
                for axis in np.where(pos != 0)[0]:
                    color = get_color_from_state_str(state_str, pos,
                                                     pos[axis] * base[axis])
                    norm = get_normal(color)
                    basis[axis] = norm * pos[axis]
                    colors[FACE_ORDER.index(color)] = True

                rot = get_rot_from_basis(basis)
                original_pos = rot.apply(pos)
                ox, oy, oz = original_pos
                id = 9 * (ox + 1) + 3 * (oy + 1) + (oz + 1)
                index = 9 * (x + 1) + 3 * (y + 1) + (z + 1)
                if index > 13:
                    index = index - 1
                if id > 13:
                    id = id - 1
                cube = Cube(initial_rotation=rot.inv(), colors=colors, id=id)
                cubes[index] = cube
                i += 1
    return np.array(cubes)