128 lines
3.4 KiB
Python
128 lines
3.4 KiB
Python
from dataclasses import dataclass
|
|
from enum import Enum
|
|
import itertools
|
|
from typing import List, Tuple, Iterator
|
|
from cube import Edge, LSECube
|
|
|
|
|
|
class EOLROrientation(Enum):
|
|
Arrow = ["UR", "UF", "UL", "DF"]
|
|
BackArrow = ["UR", "UF", "UL", "DB"]
|
|
FourZero = ["UB", "UR", "UF", "UL"]
|
|
OneOne = ["UB", "DF"]
|
|
BackOneOne = ["UB", "DB"]
|
|
SixFlip = ["UB", "UR", "UF", "UL", "DF", "DB"]
|
|
Solved = []
|
|
TwoAdjTwo = ["UB", "UR", "DF", "DB"]
|
|
TwoAdjZero = ["UB", "UR"]
|
|
TwoOppTwo = ["UB", "UF", "DF", "DB"]
|
|
TwoOppZero = ["UB", "UF"]
|
|
ZeroTwo = ["DF", "DB"]
|
|
|
|
|
|
@dataclass
|
|
class EOLRPermutation:
|
|
UR: str
|
|
UL: str
|
|
|
|
|
|
EOLR_PERMUTATIONS = [
|
|
EOLRPermutation(ur_pos, ul_pos)
|
|
for ul_pos, ur_pos in itertools.permutations(
|
|
["UB", "UR", "UF", "UL", "DF", "DB"], 2
|
|
)
|
|
]
|
|
|
|
|
|
EOLR_EDGES = [
|
|
"UB",
|
|
"UR",
|
|
"UF",
|
|
"UL",
|
|
"DF",
|
|
"DB",
|
|
]
|
|
|
|
|
|
def apply_eolr_orientation(cube: LSECube, ori: EOLROrientation):
|
|
for edge in ori.value:
|
|
cube.edges[edge].oriented = not cube.edges[edge].oriented
|
|
|
|
|
|
def apply_eolr_permutation(cube: LSECube, perm: EOLRPermutation):
|
|
cube.edges[perm.UR], cube.edges["UR"] = cube.edges["UR"], cube.edges[perm.UR]
|
|
cube.edges[perm.UL], cube.edges["UL"] = cube.edges["UL"], cube.edges[perm.UL]
|
|
|
|
|
|
def apply_eolr_auf(cube: LSECube, auf: int):
|
|
cube.cycle_corners(auf)
|
|
|
|
|
|
def eolrb_states_generator(
|
|
orientations: List[EOLROrientation], permutations: List[EOLRPermutation]
|
|
) -> Tuple[Iterator[Tuple[LSECube, EOLROrientation, EOLRPermutation, int]], int]:
|
|
num_permutations = len(orientations) * len(permutations) * 4
|
|
|
|
def generator():
|
|
for ori in orientations:
|
|
for perm in permutations:
|
|
for auf in range(4):
|
|
state = LSECube()
|
|
apply_eolr_auf(state, auf)
|
|
# applying permutation before orientation is crucial, as permutation swaps pieces and doesn't care about their orientation
|
|
apply_eolr_permutation(state, perm)
|
|
apply_eolr_orientation(state, ori)
|
|
yield (state, ori, perm, auf)
|
|
|
|
return generator(), num_permutations
|
|
|
|
|
|
def lr_solved(cube: LSECube):
|
|
return cube.edges["UR"] == Edge("UR", True) and cube.edges["UL"] == Edge("UL", True)
|
|
|
|
|
|
def eo_solved_non_mc(cube: LSECube) -> bool:
|
|
return (
|
|
cube.edges["UB"].oriented
|
|
and cube.edges["UF"].oriented
|
|
and cube.edges["DF"].oriented
|
|
and cube.edges["DB"].oriented
|
|
)
|
|
|
|
|
|
def centers_solved_non_mc(cube: LSECube) -> bool:
|
|
return cube.centers["U"] in ["U", "D"]
|
|
|
|
|
|
def eo_solved_mc(cube: LSECube) -> bool:
|
|
return (
|
|
not cube.edges["UB"].oriented
|
|
and not cube.edges["UF"].oriented
|
|
and not cube.edges["DF"].oriented
|
|
and not cube.edges["DB"].oriented
|
|
)
|
|
|
|
|
|
def centers_solved_mc(cube: LSECube) -> bool:
|
|
return cube.centers["U"] in ["F", "B"]
|
|
|
|
|
|
def eolrb_solved(cube: LSECube) -> bool:
|
|
"""
|
|
this function has weird side effects and modifies cube but we don't care about it for now
|
|
"""
|
|
if not lr_solved(cube):
|
|
return False
|
|
if centers_solved_non_mc(cube) and eo_solved_non_mc(cube):
|
|
return True
|
|
if centers_solved_mc(cube) and eo_solved_mc(cube):
|
|
return True
|
|
return False
|
|
|
|
|
|
def eolrb_solution_mc(cube: LSECube) -> bool:
|
|
"""
|
|
this function only works if eolrb is solved
|
|
"""
|
|
return centers_solved_mc(cube) and eo_solved_mc(cube)
|