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) apply_eolr_orientation(state, ori) apply_eolr_permutation(state, perm) 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)