def build_ida_graph(self):
        pt_state_filename = self.filename.replace(".txt", ".pt_state")
        parent = self.parent
        index = 0

        with open(pt_state_filename, "w") as fh_pt_state:
            with open(self.filename, "r") as fh:
                for line in fh:
                    (state, steps_to_solve) = line.rstrip().split(":")
                    steps_to_solve = steps_to_solve.split()
                    cost_to_goal = len(steps_to_solve)
                    steps_to_scramble = reverse_steps(steps_to_solve)

                    # dwalton
                    parent.re_init()
                    for step in steps_to_scramble:
                        parent.rotate(step)

                    self.init_ida_graph_nodes()
                    pt_ida_graph_nodes = self.get_ida_graph_nodes()

                    lt_state = ""

                    for x in pt_ida_graph_nodes:
                        assert x <= 9999999
                        lt_state += f"{x:07d}-"

                    lt_state = lt_state.rstrip("-")

                    fh_pt_state.write(f"{lt_state}:{cost_to_goal}\n")
                    index += 1

                    if index % 10000 == 0:
                        log.info("line: %d" % index)
    def build_ida_graph(self, start=None, end=None):
        pt_state_filename = self.filename.replace(".txt", ".pt_state")

        if start is not None:
            pt_state_filename += f"-{start}-{end}"

        for pt in self.prune_tables:
            pt.load_ida_graph()

        to_write = []
        self.init_state_index_caches()

        with open(pt_state_filename, "w") as fh_pt_state:
            with open(self.filename, "r") as fh:
                for (line_number, line) in enumerate(fh):

                    if start is not None and line_number < start:
                        continue

                    if end is not None and line_number > end:
                        break

                    (state, steps_to_solve) = line.rstrip().split(":")
                    steps_to_solve = steps_to_solve.split()

                    if state in self.state_target:
                        cost_to_goal = 0
                    else:
                        cost_to_goal = len(steps_to_solve)

                    steps_to_scramble = reverse_steps(steps_to_solve)
                    self.build_ida_graph_set_cube_state(
                        state, steps_to_scramble)
                    self.init_ida_graph_nodes()
                    pt_ida_graph_nodes = self.get_ida_graph_nodes()

                    lt_state = ""

                    for x in pt_ida_graph_nodes:
                        assert x <= 9999999
                        lt_state += f"{x:07d}-"

                    lt_state = lt_state.rstrip("-")
                    to_write.append(f"{lt_state}:{cost_to_goal}")

                    if line_number and line_number % 100000 == 0:
                        fh_pt_state.write("\n".join(to_write) + "\n")
                        to_write = []

                        if start is not None:
                            log.info(
                                f"{start:,}->{end:,} line {line_number:,}")
                        else:
                            log.info(f"line {line_number:,}")

            if to_write:
                fh_pt_state.write("\n".join(to_write) + "\n")
                to_write = []
    if "2x2x2" in filename:
        cube = RubiksCube222(solved_222, "URFDLB")
    elif "3x3x3" in filename:
        cube = RubiksCube333(solved_333, "URFDLB")
    elif "4x4x4" in filename:
        cube = RubiksCube444(solved_444, "URFDLB")
    elif "5x5x5" in filename:
        cube = RubiksCube555(solved_555, "URFDLB")
    elif "6x6x6" in filename:
        cube = RubiksCube666(solved_666, "URFDLB")
    elif "7x7x7" in filename:
        cube = RubiksCube777(solved_777, "URFDLB")
    else:
        raise Exception("What size cube?")

    for line in fh:
        (state, steps_to_solve) = line.strip().split(":")
        cube.re_init()
        cube.nuke_corners()
        # cube.nuke_edges()
        # cube.nuke_centers()
        steps_to_solve = steps_to_solve.split()
        steps_to_scramble = reverse_steps(steps_to_solve)

        for step in steps_to_scramble:
            cube.rotate(step)

        cube.print_cube()
        log.info(f"steps_to_scramble {' '.join(steps_to_scramble)}")
        log.info(f"steps_to_solve    {' '.join(steps_to_solve)}\n\n")
예제 #4
0
def build_state_table():
    cube = RubiksCube444(
        'DRFDFRUFDURDDLLUFLDLLBLULFBUUFRBLBFLLUDDUFRBURBBRBDLLDURFFBBRUFUFDRFURBUDLDBDUFFBUDRRLDRBLFBRRLB',
        'URFDLB')
    cube.nuke_corners()
    cube.nuke_edges()
    original_state = cube.state[:]

    log.info("cache start")
    for side in (cube.sideU, cube.sideL, cube.sideF, cube.sideR, cube.sideB,
                 cube.sideD):
        for pos in side.center_pos:
            if cube.state[pos] in ('U', 'D'):
                cube.state[pos] = 'U'
            elif cube.state[pos] in ('L', 'R'):
                cube.state[pos] = 'L'
            elif cube.state[pos] in ('F', 'B'):
                cube.state[pos] = 'F'

    cube.lt_UD_centers_stage = LookupTable444UDCentersStage(cube)
    cube.lt_LR_centers_stage = LookupTable444LRCentersStage(cube)
    cube.lt_FB_centers_stage = LookupTable444FBCentersStage(cube)
    lt_ULFRBD_centers_stage = LookupTableIDA444ULFRBDCentersStage(cube)

    workq = deque()
    explored = set()
    UD_explored = {}
    LR_explored = {}
    FB_explored = {}
    count = 0

    for step in moves_444:
        workq.append(([
            step,
        ], cube.state[:]))

    while workq:
        (steps, prev_state) = workq.popleft()
        cube.state = rotate_444(prev_state, steps[-1])

        state = lt_ULFRBD_centers_stage.state()
        UD_state = cube.lt_UD_centers_stage.state()
        LR_state = cube.lt_LR_centers_stage.state()
        FB_state = cube.lt_FB_centers_stage.state()

        count += 1

        if count % 100000 == 0:
            UD_count = len(UD_explored)
            LR_count = len(LR_explored)
            FB_count = len(FB_explored)

            log.info("%d UD states, %d LR state, %d FB states, %d on workq" %
                     (UD_count, LR_count, FB_count, len(workq)))

            if UD_count == 735471 and LR_count == 735471 and FB_count == 735471:
                break

        if state in explored:
            continue
        else:
            explored.add(state)
            keep_going = False

            if UD_state not in UD_explored:
                UD_explored[UD_state] = ' '.join(reverse_steps(steps))
                keep_going = True

            if LR_state not in LR_explored:
                LR_explored[LR_state] = ' '.join(reverse_steps(steps))
                keep_going = True

            if FB_state not in FB_explored:
                FB_explored[FB_state] = ' '.join(reverse_steps(steps))
                keep_going = True

            if not keep_going:
                continue

            # Only build the table 4-deep for now
            if len(steps) == 4:
                continue

            prev_step = steps[-1]

            for step in moves_444:

                # U2 followed by U2 is a no-op
                if step == prev_step and step.endswith("2"):
                    continue

                # U' followed by U is a no-op
                if prev_step.endswith("'") and not step.endswith(
                        "'") and step == prev_step[0:-1]:
                    continue

                # U followed by U' is a no-op
                if not prev_step.endswith("'") and step.endswith(
                        "'") and step[0:-1] == prev_step:
                    continue

                workq.append((steps + [
                    step,
                ], cube.state[:]))

    log.info("cache end")

    log.info("write start")

    with open('UD_state.txt', 'w') as fh:
        for key in sorted(UD_explored.keys()):
            value = UD_explored[key]
            fh.write("%s:%s\n" % (key, value))

    with open('LR_state.txt', 'w') as fh:
        for key in sorted(LR_explored.keys()):
            value = LR_explored[key]
            fh.write("%s:%s\n" % (key, value))

    with open('FB_state.txt', 'w') as fh:
        for key in sorted(FB_explored.keys()):
            value = FB_explored[key]
            fh.write("%s:%s\n" % (key, value))

    log.info("write end")
예제 #5
0
    if args.openwith:
        cube.print_cube()
        for step in args.openwith.split():
            cube.rotate(step)

    cube.cpu_mode = cpu_mode
    log.info("CPU mode %s" % cube.cpu_mode)
    cube.sanity_check()
    cube.print_cube()
    #cube.www_header()
    #cube.www_write_cube("Initial Cube")

    try:
        if args.solution333:
            #print("1")
            solution333 = reverse_steps(args.solution333.split())
        else:
            #print("1")
            solution333 = []
        cube.solve(solution333)
    except NotSolving:
        if cube.heuristic_stats:
            log.info("%s: heuristic_stats raw\n%s\n\n" %
                     (cube, pformat(cube.heuristic_stats)))

            for (key, value) in cube.heuristic_stats.items():
                cube.heuristic_stats[key] = int(median(value))

            log.info("%s: heuristic_stats median\n%s\n\n" %
                     (cube, pformat(cube.heuristic_stats)))
            sys.exit(0)
예제 #6
0
    format='%(asctime)s %(filename)20s %(levelname)8s: %(message)s')
log = logging.getLogger(__name__)

# Color the errors and warnings in red
logging.addLevelName(
    logging.ERROR,
    "\033[91m   %s\033[0m" % logging.getLevelName(logging.ERROR))
logging.addLevelName(
    logging.WARNING,
    "\033[91m %s\033[0m" % logging.getLevelName(logging.WARNING))

# Build wing_str_combos_two and wing_str_combos_four
#pprint(tuple(itertools.combinations(wing_strs_all, 2)))
#pprint(tuple(itertools.combinations(wing_strs_all, 4)))

cube = RubiksCube555(solved_555, "URFDLB")

for step in reverse_steps(
        "F Dw2 U R2 B R' Dw' Rw' Fw' B Uw' F L Uw Lw2 Dw' L Dw F' Rw' B' Rw' Lw' F U Lw F Rw2 U2 Lw2 D' Rw2 D2 Lw' D' Rw' Lw2 B' Lw' F' Dw L F' L' U' F Dw'  B' Uw' B' D' U2 B Uw  D' L' Bw U' F2 B U Bw' F B Uw' B2 R' B2 R Uw D2 B U B' D' F B' R' L' F2 D' F L B D' B' "
        .split()):
    cube.rotate(step)

cube.print_cube()

for step in "F Dw2 U R2 B R' Dw' Rw' Fw' B Uw' F L Uw Lw2 Dw' L Dw  F' Rw' B' Rw' Lw' F U Lw F Rw2 U2 Lw2 D' Rw2 D2 Lw' D' Rw' Lw2 B' Lw' ".split(
):
    cube.rotate(step)

cube.print_cube()
print(cube.get_kociemba_string(True))
def convert_lookup_table_to_graph(filename, NUMBER_COMBOS, state_is_hex,
                                  bits_to_fill):
    graph = [None] * NUMBER_COMBOS
    moves = []
    state_target = ()

    if '6x6x6' in filename:
        cube = RubiksCube666(solved_666, 'URFDLB')
        cube.lt_init()

        if (filename ==
                'lookup-table-6x6x6-step01-UD-oblique-edges-stage-left-only.txt'
                or filename ==
                'lookup-table-6x6x6-step02-UD-oblique-edges-stage-right-only.txt'
            ):
            state_target = ('UUUUxxxxxxxxxxxxxxxxUUUU', )
            moves = cube.lt_UD_oblique_edge_stage.moves_all
        else:
            raise Exception("What moves/state_target for %s?" % filename)

    else:
        raise Exception("What size cube is for %s?" % filename)

    log.info("%s: %d moves, %s" % (filename, len(moves), ' '.join(moves)))

    for state in state_target:
        state_rank = state_to_rank(state)
        log.info("%s: state %s has rank %s" % (filename, state, state_rank))
        edges = []

        for move in moves:
            cube.rotate(move)
            next_state = cube.lt_UD_oblique_edge_stage_left_only.state()
            next_state_rank = state_to_rank(next_state)

            # 730673
            if next_state_rank == state_rank:
                edges.append(None)
            else:
                edges.append(next_state_rank)

            cube.re_init()
        graph[state_rank] = (0, tuple(edges))

    with open(filename, 'r') as fh:
        for (line_number, line) in enumerate(fh):
            (state, steps_to_solve) = line.rstrip().split(':')
            steps_to_solve = steps_to_solve.split()
            cost = len(steps_to_solve)

            if state_is_hex:
                state = str(bin(int(state, 16))[2:]).zfill(bits_to_fill)
                state = state.replace('0', 'x').replace('1', 'U')
            state_rank = state_to_rank(state)
            steps_to_scramble = reverse_steps(steps_to_solve)
            #log.info("%s: state %s has rank %s" % (filename, state, state_rank))

            edges = []

            for move in moves:
                for setup_move in steps_to_scramble:
                    cube.rotate(setup_move)
                cube.rotate(move)

                next_state = cube.lt_UD_oblique_edge_stage_left_only.state()
                next_state_rank = state_to_rank(next_state)

                if next_state_rank == state_rank:
                    edges.append(None)
                else:
                    edges.append(next_state_rank)

                cube.re_init()

            graph[state_rank] = (cost, tuple(edges))
            #if line_number == 3:
            #    log.info("graph:\n%s\n" % pformat(graph))
            #    sys.exit(0)

            if line_number % 1000 == 0:
                log.info("%s %d: state %s has rank %s" %
                         (filename, line_number, state, state_rank))

                #if line_number == 1000:
                #    break

    with open(filename.replace('.txt', '.graph.txt'), 'w') as fh:
        json.dump(graph, fh, indent=4)

    none_count = 0
    for x in range(NUMBER_COMBOS):
        if graph[x] is None:
            none_count += 1

    log.info("%s: has %d entries, %d have content, %d are empty" %
             (filename, len(graph), NUMBER_COMBOS - none_count, none_count))

    return graph
예제 #8
0
def getResults(state):
    if sys.version_info < (3, 4):
        raise SystemError("Must be using Python 3.4 or higher")

    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s %(filename)22s %(levelname)8s: %(message)s")
    log = logging.getLogger(__name__)

    log.info("rubiks-cube-solver.py begin")

    start_time = dt.datetime.now()

    parser = argparse.ArgumentParser()
    parser.add_argument("--print-steps",
                        default=False,
                        action="store_true",
                        help="Display animated step-by-step solution")
    parser.add_argument("--debug",
                        default=False,
                        action="store_true",
                        help="set loglevel to DEBUG")
    parser.add_argument("--no-comments",
                        default=False,
                        action="store_true",
                        help="No comments in alg.cubing.net url")

    # CPU mode
    parser.add_argument(
        "--min-memory",
        default=False,
        action="store_true",
        help="Load smaller tables to use less memory...takes longer to run",
    )
    parser.add_argument("--fast",
                        default=True,
                        action="store_true",
                        help="Find a solution quickly")
    parser.add_argument("--normal",
                        default=False,
                        action="store_true",
                        help="Find a shorter solution but takes longer")
    parser.add_argument("--slow",
                        default=False,
                        action="store_true",
                        help="Find shortest solution we can, takes a while")

    action = parser.add_mutually_exclusive_group(required=False)
    parser.add_argument("--openwith",
                        default=None,
                        type=str,
                        help="Colors for sides U, L, etc")
    parser.add_argument("--colormap",
                        default=None,
                        type=str,
                        help="Colors for sides U, L, etc")
    parser.add_argument(
        "--order",
        type=str,
        default="URFDLB",
        help="order of sides in --state, default kociemba URFDLB")
    parser.add_argument("--solution333",
                        type=str,
                        default=None,
                        help="cube explorer optimal steps for solving 3x3x3")
    parser.add_argument(
        "--state",
        type=str,
        help="Cube state",
        # no longer used
        # parser.add_argument('--test', default=False, action='store_true')
        # 2x2x2
        #    default='DLRRFULLDUBFDURDBFBRBLFU')
        #    default='UUUURRRRFFFFDDDDLLLLBBBB')
        # 3x3x3
        #    default='RRBBUFBFBRLRRRFRDDURUBFBBRFLUDUDFLLFFLLLLDFBDDDUUBDLUU')
        #    default='UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB') # solved
        # 4x4x4
        # default='DRFDFRUFDURDDLLUFLDLLBLULFBUUFRBLBFLLUDDUFRBURBBRBDLLDURFFBBRUFUFDRFURBUDLDBDUFFBUDRRLDRBLFBRRLB') # xyzzy test cube
        # default='FLDFDLBDFBLFFRRBDRFRRURBRDUBBDLURUDRRBFFBDLUBLUULUFRRFBLDDUULBDBDFLDBLUBFRFUFBDDUBFLLRFLURDULLRU') # TPR cube
        # default="BRBLLLBRDLBBDDRRFUDFUDUDFUDDDRURBBBUUDRLFRDLLFBRFLRFLFFFBRULDRUBUBBLDBFRDLLUBUDDULFLRRFLFUBFUFUR",
    )
    #    default='UUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRFFFFFFFFFFFFFFFFDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLBBBBBBBBBBBBBBBB') # solved

    # 5x5x5
    #    default='RFFFUDUDURBFULULFDBLRLDUFDBLUBBBDDURLRDRFRUDDBFUFLFURRLDFRRRUBFUUDUFLLBLBBULDDRRUFUUUBUDFFDRFLRBBLRFDLLUUBBRFRFRLLBFRLBRRFRBDLLDDFBLRDLFBBBLBLBDUUFDDD')
    #    https://www.speedsolving.com/forum/threads/arnauds-5x5x5-edge-pairing-method-examples.1447/
    #    default='LDFRDDUUUUFUUUBLUUUFLDFDRFDDFBBRRRULRRRBFRRRURFRFDUBDRUBFFFUBFFFUUFFFRLDLRFDLBDDLDDDRDDDDUDDDDUULDLFBFLFFULLLRFLLLRLLLLRRBLBBRBULULBBBRUBBBRBBBBULBRFB')
    #    default='UDLFDLDDLUFDUBRLBDLFLRBFRBLBBFUDURDULRRBRLFUURBUFLUBDUDRURRRBUFUFFFRUFFLDUURURFFULFFRLFDBRRFRDDBRFBBLBRDFBBBBUDDLLLDBUULUDULDLDDLBRRLRLUBBFFBDLFBDDLFR')
    #    default='UUUUUUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLBBBBBBBBBBBBBBBBBBBBBBBBB') # solved
    #    default='DFFURRULDLDLURLBDDRRBFRURFBFBFRBDLBBFRBLRFBRBBFLULDLBLULLFRUBUFLDFFLDULDDLUURRDRFBRLULUDRBDUUUBBRFFDBDFURDBBDDRULBUDRDLLLBDRFDLRDLLFDBBUFBRURFFUFFUUFU') # step10 takes 2s
    #    default='URUBFUUFRDFFUUFLRDBLLBDDDLUULRDLDUBDLRBBLFLBRBFUUBBRBFFUDLFLLBFUFUDRLBFUBBURRLLRUFRDUFFDFRFUBRBBDRFRFLLFURLLFBRBLUDRDDRRDRRFDUDLFLDLUUDUDBRBBBRBDDLDFL') # step10 takes 9s
    #    default='RFUBLFUBRULLUDDRLRLLFFFLUBDBLBFFUFLFURBFFLDDLFFBBRLUUDRRDLLLRDFFLBBLFURUBULBRLBDRUURDRRDFURDBUUBBFBUDRUBURBRBDLFLBDFBDULLDBBDDDRRFURLDUDUBRDFRFFDFDRLU') # step10 takes 6s, centers take 37 steps :(

    # 6x6x6
    #    default='FBDDDFFUDRFBBLFLLURLDLLUFBLRFDUFLBLLFBFLRRBBFDRRDUBUFRBUBRDLUBFDRLBBRLRUFLBRBDUDFFFDBLUDBBLRDFUUDLBBBRRDRUDLBLDFRUDLLFFUUBFBUUFDLRUDUDBRRBBUFFDRRRDBULRRURULFDBRRULDDRUUULBLLFDFRRFDURFFLDUUBRUFDRFUBLDFULFBFDDUDLBLLRBL')
    #    default='UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUURRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB') # solved
    #    defult='xxxxxxxDRRLxxLDDBxxLUUDxxFRDUxxxxxxxxxxxxxxBBLBxxURFUxxDRBDxxDFDLxxxxxxxxxxxxxxULLRxxUFLLxxBLFRxxBBRDxxxxxxxxxxxxxxLFBRxxBUUFxxFDDFxxURUFxxxxxxxxxxxxxxRFDLxxURFUxxUBBFxxRULDxxxxxxxxxxxxxxBBLFxxFLLRxxDRBBxxFDRUxxxxxxx') # good step20 IDA test

    # 7x7x7
    #    default='DBDBDDFBDDLUBDLFRFRBRLLDUFFDUFRBRDFDRUFDFDRDBDBULDBDBDBUFBUFFFULLFLDURRBBRRBRLFUUUDUURBRDUUURFFFLRFLRLDLBUFRLDLDFLLFBDFUFRFFUUUFURDRFULBRFURRBUDDRBDLLRLDLLDLUURFRFBUBURBRUDBDDLRBULBULUBDBBUDRBLFFBLRBURRUFULBRLFDUFDDBULBRLBUFULUDDLLDFRDRDBBFBUBBFLFFRRUFFRLRRDRULLLFRLFULBLLBBBLDFDBRBFDULLULRFDBR')

    # 8x8x8
    #    default='DRRRURBDDBFBRBDDBRRDUFLLURFBFLFURLFLFRBRFUBDRFDFUUBLFFFUULBBFDBDFBUBBFRFLRDLFDRBBLLFRLDFDRBURULDDRFFBFUUBLLFBRUUFDUBRDBBRDFLURUUFFUDLBRRFDUBFLRUUFFRLBFRFLRULUDFRUBBDBFFLBBDFDFLDBFRRRDDLFLBRBFBBRULDDUUBLBBURULLDDLDRUDRBUDRLUULDURLRDFLFULUFLFULRDDDUBBULRBRDFBBLFURRLULUBDDULRFBRFURBRLBRUBULBDDFBUFFBBRLRUUUFRULLBFFRFDDFFDULLDLBUDLLLLUUBBLDLLBBULULBDUDDFUBFLLDLDLFRDUDDBRRFRURRFRRLDDDDRD')

    # 9x9x9
    #    default='RFBLRUFLLFFLRRBDUDDBBBDUDFRUDUFFFBBFRBRDURBULFUDDFLLLDLFLRDLDBBBUUBRDBBBDFUFRUURULURBURDLFDUBFFDRDFRUBDUBRFLRRLUDLRLFBLBRRLLRDRBRBLURBLLRFRLDDFFFRBFUFURDFRRUDUFDDRRRLFLLUBBLBFDRRDLBRLUUBRDBBUBFLUUFBLLDBFFFBUFBFDBRDDDFLRFFBFFFLFRRDUUDDBUBLUUDURRBDBFFLFURDDLUBULUULULBFBRUBLLDDFLRBDBRFDUUDFURLLUBUFBLULLURDLLLBLFFRLLBLUDRLRDBLDDBRBUDRBLLRDUUUBRRFBFBBULUDUDLDRFUDDDFULRFRBDUDULBRRDBDFFRUUFRRFBDBLFBBDFURLRFDUUFRLUBURFURDDFLDFUBDFRRURRDLUDRBRBDLBFLBBRDLRDBFDUBDFFUBLFLUULLBUDLLLURDBLFFFDFLF'

    # 10x10x10
    #    default='ULBDLDBUFRBBBBBLBFFFDFRFBBDDFDFRFFLDLDLURRBUDRRBFLUDFRLBDURULRUUDBBBUBRURRRLDLRFFUFFFURRFBLLRRFLFUDBDRRDFULLLURFBFUUBDBBDBFLFDFUUFDUBRLUFDBLRFLUDUFBFDULDFRUBLBBBUBRRDBDDDDFURFLRDBRRLLRFUFLRDFDUULRRDULFDUDRFLBFRLDUDBDFLDBDUFULULLLBUUFDFFDBBBRBRLFLUFLFUFFRLLLFLBUDRRFDDUDLFLBRDULFLBLLULFLDLUULBUDRDFLUDDLLRBLUBBRFRRLDRDUUFLDDFUFLBDBBLBURBBRRRFUBLBRBRUBFFDBBBBLBUFBLURBLDRFLFBUDDFFRFFRLBDBDUURBUFBDFFFLFBDLDUFFBRDLBRLRLBFRUUUULRRBDBRRFDLLRRUUBDBDBFDLRDDBRUUUUUBLLURBDFUFLLRDBLRRBBLBDDBBFUDUDLDLUFDDDUURBFUFRRBLLURDDRURRURLBLDRFRUFBDRULUFFDUDLBBUURFDUDBLRRUDFRLLDULFUBFDLURFBFULFLRRRRRFDDDLFDDRUFRRLBLUBU')

    # 14x14x14
    #    default='FBDRLBLRRURRLDRBDLBURDFDDDRBLBBFBRDLLFDUBLFRLDFUUBFRDBFBBBULFRLBUFLBDDDLLDRBFLLBBLFBFFDFBFDDFRRRBDRRBRBDUFDRLRUDLDFDDURFLBUBBUUDLBRRDUDRDBBBLDBRBBBUFLBLRUURBDDLDRLUFFBLFRLDFBRFLDLBULFFBRLDBDDFLLRFLUBFDFBRLRLFDBLBURLBLFRFBLLDULUDURLBUUULLRRLUBDDLURLLRFURFRFRBDDUBLDFBLUDRLRDRRBLFUFRDUFFRULBLRBBRUFDBUBBBBLDBRBLDDRRFDDBFFUUBRBLFUBBRFUURBFDRLURLRBFUUFUBRUDRBDFBBFURFLFFDRDFUFFULFLUBDFUFFDLRRFRUDUDLBBBDLLLDUFUDRFDBLRRFFLRUFDRFURDLRRDRDLFBRLRLULRFBDLFDRLFRDDFLLDBFBUBBRLLDLFURFRFULUBLUBFLFFBFDFBDUUBURUUUBFUBDLLFLUUUFDUDLUUULDLLUDDBUFRDRULRLLULRULFBLUDFURFLFUBDLLFLFUBUUBBUFLUDUBRDBLFFUUUFDRLRULUDDRLRBLRUUFBRRRRULBDLFBFLDLRDFUBLUBRDDFUULFLDLUBFURRURUBDFFFDLRFFLBRFRDRUDUULURULLDFRBUDRDLFUFULDBLUBFRFBURDLLUUFDURLRDBLFFRFDBFURLFUBLUUUFFRULUBURRURFDDBFUFRBURBBDRFUDDFDLRUURFBBDBDRLUBRRBFDFRDFDLRDUFFUBRRBDBBLDLFDUDDRLFRRRBUUUBRFUFBUFFBRRDRDDBBDRUULDRFRFBUFLFFBLRBFLLLRUDFDRUDLDRLFRLUFLUBRDUFDDLLUDDRBUBBBDRDBBFRBDDRRLRRUUBBUDUDBLDBDFLFRFUBFLFDBBLRLULDBRFBRRLUUURDFFFDBLDUDBRFDDFFUBLUUURBBULFUFUDFBRDLLFURBULULBUDLUFFBDRBRRDBUUULFDURRDFDDLUDBDRBFBUFLULURUFDRFRFBBFBBBDRLBLUDLDRDLLDRRLLDLFBRBRLDUFBDDUDBLDFRFBBBDRDRDDLDRULFFLLFLBLDFLURLBUDFBDLRBLFDFLUDDFUBUBLURBBBLFRLFLBDDBURFFBFRRL')

    # 15x15x15
    #    default='RLURLURBDDULFUUURFLRBLURUBFDBULFLUBBFLDUFBDRFRBRUDFULFRUFLUDFRLFDFLLFDBULURRLBFBUURDULFDFBLRRRLFULLFFFDUULRRRUUUUFDBLDDFFLRDLLUURUBBULUFFURBRRLBBUUBBFDRRBRBRLUDLUDRBFBFULLRRBBFBFRDDDLDDDFRFUFLURUFLBDLUBRLDFRRDBDBFLFUDFLDFFURLFULLDDRURRDLRFLDFLULUUDDRFDRBLRBRBFUFDBDUUDBRRBDFBLBLRBBLBFLLDUBFFFFBDDRLBBBRFDFFUBBDURFLUUDDDRDDLDBRLBULLFLFBRBRBLUDDLRDRDUDFLFRUFLDLBLURDDDRUFDLBRDRLFBDBLDRFBFFBURULUDRRBRDFRFFLULLUBRDRRRDUFRBLFULUBBUFFBRBBFRLFDRRDBLDFRDRDDRLRUULBDURDURFDDLFDUUDBFLBDUFBULFRRDUDUBFBUDBBFUDFUUDLUDDRFDDDFRRRBUDRBFBBULLUFBLRLFLLBRRRRUBDRFLFDFDBLRFLURULULFFBUUUUFDBBLDLUBBRUBBBRBFLULLBLUUULLUBFFDULDFFBFFFUFFDUDRFBUFLDDLURFLRFLRFBUUBLRFDDRULUUUFFRDDBLRDULFURUDDBDLBBUUBFURFRFBRLBUULBLDDDBUBRFFULLUDFFDLDFUBLLBLDFFDDLBDUFUFFLBBBUBULDDFBRRFFLDUDDFRBLRRDDUDLBDBLURBUDBRRLUBBDRFBUFRDRDRBBDULBUFFDRBBDFBUULFFRLLDURRRDFFUUFULDULURLDLUUUDLBBUDLDRFBDBBDLUFBRRFDFLLDLFDBRBBRFUDDDBURDRBUBRUBDUBLDLLDLURLDFDBRUBDLDFRRRBRLULFRFLDRLBUBRUBLFBFDFFLFRFDFLBRULLRBLDRBBFURRRDUUULLULLDLBLBBDFBUUUBRRUFFBRUDBFRDFDLFLFFRFFFFRULDFFDFRUBBBRURBUFLBDFBBBBBRRRLFLFBDRRUFLURDDLRRBRLLFURRURBRFLLLFFURBFULFRFFBLDUUUUBDDUFFDRBRLDDFRBULDDDFFRURUFLDRFLDFBLRUFFUBBDFFDBLLDBDUBDLDLUDFBFLRULRRBDBLRBLDLUURRLLRULDBLBLLRRFDDRBBRBUBDDULDRFBFBBFLUFBLUULDDFDBRLLUBUBBDFBBLBBUBLULDRUDBLRULDUDLUFRRDLLUDDBUFLFLBUFUURFDRDLBURLLRRRULRBFFRRBRFBUBRBUUFRLRDRDLBBRFLLLDDBRFUFRBULFLFDRDDRRDBF')

    args = parser.parse_args()
    args.state = state
    if "G" in args.state:
        args.state = args.state.replace("G", "F")
        args.state = args.state.replace("Y", "D")
        args.state = args.state.replace("O", "L")
        args.state = args.state.replace("W", "U")

    if args.debug:
        log.setLevel(logging.DEBUG)

    try:
        size = int(sqrt((len(args.state) / 6)))

        if args.slow:
            cpu_mode = "slow"
        elif args.normal:
            cpu_mode = "normal"
        elif args.fast:
            cpu_mode = "fast"
        else:
            raise Exception("What CPU mode to use?")

        if size == 2:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube222 import RubiksCube222

            cube = RubiksCube222(args.state, args.order, args.colormap,
                                 args.debug)
        elif size == 3:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube333 import RubiksCube333

            cube = RubiksCube333(args.state, args.order, args.colormap,
                                 args.debug)
        elif size == 4:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube444 import RubiksCube444

            cube = RubiksCube444(args.state,
                                 args.order,
                                 args.colormap,
                                 avoid_pll=True,
                                 debug=args.debug)
        elif size == 5:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube555 import RubiksCube555

            cube = RubiksCube555(args.state, args.order, args.colormap,
                                 args.debug)
        elif size == 6:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube666 import RubiksCube666

            cube = RubiksCube666(args.state, args.order, args.colormap,
                                 args.debug)
        elif size == 7:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCube777 import RubiksCube777

            cube = RubiksCube777(args.state, args.order, args.colormap,
                                 args.debug)
        elif size % 2 == 0:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCubeNNNEven import RubiksCubeNNNEven

            cube = RubiksCubeNNNEven(args.state, args.order, args.colormap,
                                     args.debug)
        else:
            # rubiks cube libraries
            from rubikscubennnsolver.RubiksCubeNNNOdd import RubiksCubeNNNOdd

            cube = RubiksCubeNNNOdd(args.state, args.order, args.colormap,
                                    args.debug)

        if args.openwith:
            cube.print_cube()
            for step in args.openwith.split():
                cube.rotate(step)

        cube.cpu_mode = cpu_mode
        log.info("CPU mode %s" % cube.cpu_mode)
        cube.sanity_check()
        cube.print_cube()
        cube.www_header()
        cube.www_write_cube("Initial Cube")

        try:
            if args.solution333:
                solution333 = reverse_steps(args.solution333.split())
            else:
                solution333 = []
            cube.solve(solution333)
        except NotSolving:
            if cube.heuristic_stats:
                log.info("%s: heuristic_stats raw\n%s\n\n" %
                         (cube, pformat(cube.heuristic_stats)))

                for (key, value) in cube.heuristic_stats.items():
                    cube.heuristic_stats[key] = int(median(value))

                log.info("%s: heuristic_stats median\n%s\n\n" %
                         (cube, pformat(cube.heuristic_stats)))
                sys.exit(0)
            else:
                raise

        end_time = dt.datetime.now()
        log.info("Final Cube")
        cube.print_cube()
        res = cube.print_solution(not args.no_comments)

        log.info(
            "*********************************************************************************"
        )
        log.info(
            "See /tmp/rubiks-cube-NxNxN-solver/index.html for more detailed solve instructions"
        )
        log.info(
            "*********************************************************************************\n"
        )

        # Now put the cube back in its initial state and verify the solution solves it
        solution = cube.solution
        cube.re_init()
        len_steps = len(solution)

        for (i, step) in enumerate(solution):

            if args.print_steps:
                print(("Phase     : %s" % cube.phase()))
                print(("Move %d/%d: %s" % (i + 1, len_steps, step)))

            cube.rotate(step)

            www_desc = "Phase: %s<br>\nCube After Move %d/%d: %s<br>\n" % (
                cube.phase(), i + 1, len_steps, step)
            cube.www_write_cube(www_desc)

            if args.print_steps:
                cube.print_cube()
                print("\n\n\n\n")

        cube.www_footer()

        if args.print_steps:
            cube.print_cube()

        if args.min_memory:
            print("\n\n****************************************")
            print("--min-memory has been replaced by --fast")
            print("****************************************\n\n")

        log.info("rubiks-cube-solver.py end")
        log.info("Memory : {:,} bytes".format(
            resource.getrusage(resource.RUSAGE_SELF).ru_maxrss))
        log.info("Time   : %s" % (end_time - start_time))
        log.info("")

        success = True

        if not cube.solved():
            kociemba_string = cube.get_kociemba_string(False)
            # edge_swap_count = cube.get_edge_swap_count(edges_paired=True, orbit=None, debug=True)
            # corner_swap_count = cube.get_corner_swap_count(debug=True)

            # raise SolveError("cube should be solved but is not, edge parity %d, corner parity %d, kociemba %s" %
            #    (edge_swap_count, corner_swap_count, kociemba_string))
            raise SolveError("cube should be solved but is not")

    except (ImplementThis, SolveError, StuckInALoop, NoSteps, KeyError,
            NoPruneTableState, InvalidCubeReduction):
        cube.enable_print_cube = True
        cube.print_cube_layout()
        cube.print_cube()
        res = cube.print_solution(False)
        success = True
        print((cube.get_kociemba_string(True)))
        log.info("rubiks-cube-solver.py end")
        raise

    return res, success