CoCalc Public Filestmp / 2017-02-25-152742-rubiks.sagews.htmlOpen in with one click!
Authors: Harald Schilly, ℏal Snyder, William A. Stein
tmp/2017-02-25-152742-rubiks.sagews

tmp/2017-02-25-152742-rubiks.sagews

AuthorWilliam Stein
Date2017-02-25T23:35:07
Project4a5f0542-5873-4eed-a85c-a18c706e8bcd
Locationtmp/2017-02-25-152742-rubiks.sagews
Original file2017-02-25-152742-rubiks.sagews
C = RubiksCube()C
+--------------+ | 1 2 3 | | 4 top 5 | | 6 7 8 | +------------+--------------+-------------+------------+ | 9 10 11 | 17 18 19 | 25 26 27 | 33 34 35 | | 12 left 13 | 20 front 21 | 28 right 29 | 36 rear 37 | | 14 15 16 | 22 23 24 | 30 31 32 | 38 39 40 | +------------+--------------+-------------+------------+ | 41 42 43 | | 44 bottom 45 | | 46 47 48 | +--------------+
RubiksCube??
   File: /projects/sage/sage-7.5/local/lib/python2.7/site-packages/sage/groups/perm_gps/cubegroup.py
   Source:
   class RubiksCube(SageObject):
    r"""
    The Rubik's cube (in a given state).

    EXAMPLES::

        sage: C = RubiksCube().move("R U R'")
        sage: C.show3d()

    ::

        sage: C = RubiksCube("R*L"); C
                     +--------------+
                     | 17    2   38 |
                     | 20   top  36 |
                     | 22    7   33 |
        +------------+--------------+-------------+------------+
        | 11  13  16 | 41   18    3 | 27   29  32 | 48  34   6 |
        | 10 left 15 | 44  front  5 | 26 right 31 | 45 rear  4 |
        |  9  12  14 | 46   23    8 | 25   28  30 | 43  39   1 |
        +------------+--------------+-------------+------------+
                     | 40   42   19 |
                     | 37 bottom 21 |
                     | 35   47   24 |
                     +--------------+
        sage: C.show()
        sage: C.solve(algorithm='gap')  # long time
        'L R'
        sage: C == RubiksCube("L*R")
        True
    """
    def __init__(self, state=None, history=[], colors=[lpurple,yellow,red,green,orange,blue]):
        """
        Initialize ``self``.

        EXAMPLES::

            sage: C = RubiksCube().move("R*U")
            sage: TestSuite(C).run()
        """
        self.colors = colors
        self._history = history
        self._group = CubeGroup()
        if state is None:
            self._state = self._group.identity()
        else:
            if isinstance(state, str):
                state = self._group.faces(state)
            if not isinstance(state, PermutationGroupElement):
                legal, state = self._group.legal(state, mode="gimme_group_element")
                if not legal:
                    raise ValueError("Not a legal cube.")
            self._state = state

    def move(self, g):
        r"""
        Move the Rubik's cube by ``g``.

        EXAMPLES::

            sage: RubiksCube().move("R*U") == RubiksCube("R*U")
            True
        """
        if not isinstance(g, self._group._element_class()):
            g = self._group.move(g)[0]
        return RubiksCube(self._state * g, self._history + [g], self.colors)

    def undo(self):
        r"""
        Undo the last move of the Rubik's cube.

        EXAMPLES::

            sage: C = RubiksCube()
            sage: D = C.move("R*U")
            sage: D.undo() == C
            True
        """
        if len(self._history) == 0:
            raise ValueError("no moves to undo")
        g = self._history[-1]
        return RubiksCube(self._state * ~g, self._history[:-1], self.colors)

    def _repr_(self):
        r"""
        Return a string representation of ``self``.

        EXAMPLES::

            sage: RubiksCube().move("R*U")
                         +--------------+
                         |  3    5   38 |
                         |  2   top  36 |
                         |  1    4   25 |
            +------------+--------------+-------------+------------+
            | 33  34  35 |  9   10    8 | 19   29  32 | 48  26  27 |
            | 12 left 13 | 20  front  7 | 18 right 31 | 45 rear 37 |
            | 14  15  16 | 22   23    6 | 17   28  30 | 43  39  40 |
            +------------+--------------+-------------+------------+
                         | 41   42   11 |
                         | 44 bottom 21 |
                         | 46   47   24 |
                         +--------------+
            
        """
        return self._group.repr2d(self._state)

    def facets(self):
        r"""
        Return the facets of ``self``.

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.facets()
            [3, 5, 38, 2, 36, 1, 4, 25, 33, 34, 35, 12, 13, 14, 15, 16, 9, 10,
             8, 20, 7, 22, 23, 6, 19, 29, 32, 18, 31, 17, 28, 30, 48, 26, 27,
             45, 37, 43, 39, 40, 41, 42, 11, 44, 21, 46, 47, 24]
        """
        return self._group.facets(self._state)

    def plot(self):
        r"""
        Return a plot of ``self``.

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.plot()
            Graphics object consisting of 55 graphics primitives
        """
        return self._group.plot_cube(self._state)

    def show(self):
        r"""
        Show a plot of ``self``.

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.show()
        """
        self.plot().show()

    def cubie(self, size, gap, x,y,z, colors, stickers=True):
        """
        Return the cubie at `(x,y,z)`.

        INPUT:

        - ``size`` -- The size of the cubie
        - ``gap`` -- The gap between cubies
        - ``x,y,z`` -- The position of the cubie
        - ``colors`` -- The list of colors
        - ``stickers`` -- (Default ``True``) Boolean to display stickers

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.cubie(0.15, 0.025, 0,0,0, C.colors*3)
            Graphics3d Object
        """
        sides = cubie_face_list[x,y,z]
        t = 2*size+gap
        my_colors = [colors[sides[i]+6] for i in range(6)]
        if stickers:
            B = Box(size, size, size, color=(.1, .1, .1))
            S = B + B.stickers(my_colors, size*.1, size*.01)
            return S.translate(-t*x, -t*z, -t*y)
        else:
            return ColorCube(size, [colors[sides[i]+6] for i in range(6)]).translate(-t*x, -t*z, -t*y)

    def plot3d(self, stickers=True):
        r"""
        Return a 3D plot of ``self``.

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.plot3d()
            Graphics3d Object
        """
        while len(self.colors) < 7:
            self.colors.append((.1, .1, .1))
        side_colors = [Texture(color=c, ambient=.75) for c in self.colors]
        start_colors = sum([[c]*8 for c in side_colors], [])
        facets = self._group.facets(self._state)
        facet_colors = [0]*48
        for i in range(48):
            facet_colors[facets[i]-1] = start_colors[i]
        all_colors = side_colors + facet_colors
        pm = [-1,0,1]
        C = sum([self.cubie(.15, .025, x, y, z, all_colors, stickers) for x in pm for y in pm for z in pm], Box(.35, .35, .35, color=self.colors[-1]))
        return C.rotateZ(1.5) #.scale([1,-1,1]).rotateZ(1.5)

    def show3d(self):
        r"""
        Show a 3D plot of ``self``.

        EXAMPLES::

            sage: C = RubiksCube("R*U")
            sage: C.show3d()
        """
        return self.plot3d().show()

    def __cmp__(self, other):
        """
        Comparison.

        EXAMPLES::

            sage: C = RubiksCube()
            sage: D = RubiksCube("R*U")
            sage: C < D
            True
            sage: C > D
            False
            sage: C == C
            True
            sage: C != D
            True
        """
        c = cmp(type(self), type(other))
        if c == 0:
            return cmp(self._state, other._state)
        else:
            return c

    def solve(self, algorithm="hybrid", timeout=15):
        r"""
        Solve the Rubik's cube.

        INPUT:

        - ``algorithm`` -- must be one of the following:

          - ``hybrid`` - try ``kociemba`` for timeout seconds, then ``dietz``
          - ``kociemba`` - Use Dik T. Winter's program
            (reasonable speed, few moves)
          - ``dietz`` - Use Eric Dietz's cubex program
            (fast but lots of moves)
          - ``optimal`` - Use Michael Reid's optimal program
            (may take a long time)
          - ``gap`` - Use GAP word solution (can be slow)

        EXAMPLES::

            sage: C = RubiksCube("R U F L B D")
            sage: C.solve()
            'R U F L B D'

        Dietz's program is much faster, but may give highly non-optimal
        solutions::

            sage: s = C.solve('dietz'); s
            "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'"
            sage: C2 = RubiksCube(s)
            sage: C == C2
            True
        """
        import sage.interfaces.rubik # here to avoid circular referencing
        if algorithm == "default":
            algorithm = "hybrid"

        if algorithm == "hybrid":
            try:
                solver = sage.interfaces.rubik.DikSolver()
                return solver.solve(self.facets(), timeout=timeout)
            except RuntimeError:
                solver = sage.interfaces.rubik.CubexSolver()
                return solver.solve(self.facets())

        elif algorithm == "kociemba":
            solver = sage.interfaces.rubik.DikSolver()
            return solver.solve(self.facets(), timeout=timeout)

        elif algorithm == "dietz":
            solver = sage.interfaces.rubik.CubexSolver()
            return solver.solve(self.facets())

        elif algorithm == "optimal":
            # TODO: cache this, startup is expensive
            solver = sage.interfaces.rubik.OptimalSolver()
            return solver.solve(self.facets())

        elif algorithm == "gap":
            solver = CubeGroup()
            return solver.solve(self._state)

        else:
            raise ValueError("Unrecognized algorithm: %s" % algorithm)

    def scramble(self, moves=30):
        """
        Scramble the Rubik's cube.

        EXAMPLES::

            sage: C = RubiksCube()
            sage: C.scramble() # random
                         +--------------+
                         | 38   29   35 |
                         | 20   top  42 |
                         | 11   44   30 |
            +------------+--------------+-------------+------------+
            | 48  13  17 |  6   15   24 | 43   23   9 |  1  36  32 |
            |  4 left 18 |  7  front 37 | 12 right 26 |  5 rear 10 |
            | 33  31  40 | 14   28    8 | 25   47  16 | 22   2   3 |
            +------------+--------------+-------------+------------+
                         | 46   21   19 |
                         | 45 bottom 39 |
                         | 27   34   41 |
                         +--------------+
            
        """
        last_move = move = "  "
        all = []
        for i in range(moves):
            while move[0] == last_move[0]:
                move = "RLUDBF"[random.randint(0,5)] + " '2"[random.randint(0,2)]
            last_move = move
            all.append(move)
        return self.move(' '.join(all))
C = RubiksCube("R*U*R")show(C.plot3d(), spin=1)
C._state
(1,38,19,33,24,6)(2,36,21,7,4)(3,43,11,35,32,25)(5,45)(8,27,30,17,9,48)(10,34,29,28,18)(26,31)
C.solve()
'R U R'
C = RubiksCube??()
C = C.scramble()
C.show()
C.plot3d()
C.solve()
"R2 B' L2 F D2 B2 R2 U2 D' R' B F U L D' L R2 B2 F2"