def verify(s): """ Check if the cube definition string s represents a solvable cube. @param s is the cube definition string , see {@link Facelet} @return 0: Cube is solvable<br> -1: There is not exactly one facelet of each colour<br> -2: Not all 12 edges exist exactly once<br> -3: Flip error: One edge has to be flipped<br> -4: Not all 8 corners exist exactly once<br> -5: Twist error: One corner has to be twisted<br> -6: Parity error: Two corners or two edges have to be exchanged """ count = [0] * 6 # new int[6] try: for i in xrange(54): assert s[i] in colors count[colors[s[i]]] += 1 except: return -1 for i in xrange(6): if count[i] != 9: return -1 fc = FaceCube(s) cc = fc.toCubieCube() return cc.verify()
def toFaceCube(self): """return cube in facelet representation""" fcRet = FaceCube() for i in corner_values: j = self.cp[i] # cornercubie with index j is at cornerposition with index i ori = self.co[i] # Orientation of this cubie for n in xrange(3): _butya = FaceCube.cornerFacelet[i][(n + ori) % 3] fcRet.f[_butya] = FaceCube.cornerColor[j][n] for i in edge_values: ori = self.eo[i] # Orientation of this cubie for n in xrange(2): _butya = FaceCube.edgeFacelet[i][(n + ori) % 2] fcRet.f[_butya] = FaceCube.edgeColor[self.ep[i]][n] return fcRet
def toFaceCube(self): """return cube in facelet representation""" fcRet = FaceCube() for i in corner_values: j = self.cp[ i] # cornercubie with index j is at cornerposition with index i ori = self.co[i] # Orientation of this cubie for n in xrange(3): _butya = FaceCube.cornerFacelet[i][(n + ori) % 3] fcRet.f[_butya] = FaceCube.cornerColor[j][n] for i in edge_values: ori = self.eo[i] # Orientation of this cubie for n in xrange(2): _butya = FaceCube.edgeFacelet[i][(n + ori) % 2] fcRet.f[_butya] = FaceCube.edgeColor[self.ep[i]][n] return fcRet
def solution(self, facelets, maxDepth, timeOut, useSeparator): """ Computes the solver string for a given cube. @param facelets is the cube definition string, see {@link Facelet} for the format. @param maxDepth defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually will return a solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few seconds on average to find a solution, but it may take much longer for specific cubes. @param timeOut defines the maximum computing time of the method in seconds. If it does not return with a solution, it returns with an error code. @param useSeparator determines if a " . " separates the phase1 and phase2 parts of the solver string like in F' R B R L2 F . U2 U D for example.<br> @return The solution string or an error code:<br> Error 1: There is not exactly one facelet of each colour<br> Error 2: Not all 12 edges exist exactly once<br> Error 3: Flip error: One edge has to be flipped<br> Error 4: Not all corners exist exactly once<br> Error 5: Twist error: One corner has to be twisted<br> Error 6: Parity error: Two corners or two edges have to be exchanged<br> Error 7: No solution exists for the given maxDepth<br> Error 8: Timeout, no solution within given time """ # +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++ count = [0] * 6 try: for i in xrange(54): assert facelets[i] in colors count[colors[facelets[i]]] += 1 except Exception as e: return "Error 1" for i in xrange(6): if count[i] != 9: return "Error 1" fc = FaceCube(facelets) cc = fc.toCubieCube() s = cc.verify() if s != 0: return "Error %s" % abs(s) # +++++++++++++++++++++++ initialization +++++++++++++++++++++++++++++++++ c = CoordCube(cc) self.po[0] = 0 self.ax[0] = 0 self.flip[0] = c.flip self.twist[0] = c.twist self.parity[0] = c.parity self.slice[0] = c.FRtoBR / 24 self.URFtoDLF[0] = c.URFtoDLF self.FRtoBR[0] = c.FRtoBR self.URtoUL[0] = c.URtoUL self.UBtoDF[0] = c.UBtoDF self.minDistPhase1[1] = 1 # else failure for depth=1, n=0 mv = 0 n = 0 busy = False depthPhase1 = 1 tStart = time.time() # +++++++++++++++++++ Main loop ++++++++++++++++++++++++++++++++++++++++++ while True: while True: if depthPhase1 - n > self.minDistPhase1[n + 1] and not busy: if self.ax[n] == 0 and self.ax[ n] == 3: # Initialize next move n += 1 self.ax[n] = 1 else: n += 1 self.ax[n] = 0 self.po[n] = 1 else: self.po[n] += 1 if self.po[n] > 3: while True: # increment axis self.ax[n] += 1 if self.ax[n] > 5: if time.time() - tStart > timeOut: return "Error 8" if n == 0: if depthPhase1 >= maxDepth: return "Error 7" else: depthPhase1 += 1 self.ax[n] = 0 self.po[n] = 1 busy = False break else: n -= 1 busy = True break else: self.po[n] = 1 busy = False if not (n != 0 and (self.ax[n - 1] == self.ax[n] or self.ax[n - 1] - 3 == self.ax[n])): break else: busy = False if not busy: break # +++++++++++++ compute new coordinates and new minDistPhase1 ++++++++++ # if minDistPhase1 =0, the H subgroup is reached mv = 3 * self.ax[n] + self.po[n] - 1 self.flip[n + 1] = CoordCube.flipMove[self.flip[n]][mv] self.twist[n + 1] = CoordCube.twistMove[self.twist[n]][mv] self.slice[n + 1] = CoordCube.FRtoBR_Move[self.slice[n] * 24][mv] / 24 self.minDistPhase1[n + 1] = max( getPruning( CoordCube.Slice_Flip_Prun, CoordCube.N_SLICE1 * self.flip[n + 1] + self.slice[n + 1]), getPruning( CoordCube.Slice_Twist_Prun, CoordCube.N_SLICE1 * self.twist[n + 1] + self.slice[n + 1])) # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if self.minDistPhase1[n + 1] == 0 and n >= depthPhase1 - 5: self.minDistPhase1[ n + 1] = 10 # instead of 10 any value >5 is possible if n == depthPhase1 - 1: s = self.totalDepth(depthPhase1, maxDepth) if s >= 0: if (s == depthPhase1 or (self.ax[depthPhase1 - 1] != self.ax[depthPhase1] and self.ax[depthPhase1 - 1] != self.ax[depthPhase1] + 3)): return self.solutionToString( s, depthPhase1 ) if useSeparator else self.solutionToString(s)
def solution(self, facelets, maxDepth, timeOut, useSeparator): """ Computes the solver string for a given cube. @param facelets is the cube definition string, see {@link Facelet} for the format. @param maxDepth defines the maximal allowed maneuver length. For random cubes, a maxDepth of 21 usually will return a solution in less than 0.5 seconds. With a maxDepth of 20 it takes a few seconds on average to find a solution, but it may take much longer for specific cubes. @param timeOut defines the maximum computing time of the method in seconds. If it does not return with a solution, it returns with an error code. @param useSeparator determines if a " . " separates the phase1 and phase2 parts of the solver string like in F' R B R L2 F . U2 U D for example.<br> @return The solution string or an error code:<br> Error 1: There is not exactly one facelet of each colour<br> Error 2: Not all 12 edges exist exactly once<br> Error 3: Flip error: One edge has to be flipped<br> Error 4: Not all corners exist exactly once<br> Error 5: Twist error: One corner has to be twisted<br> Error 6: Parity error: Two corners or two edges have to be exchanged<br> Error 7: No solution exists for the given maxDepth<br> Error 8: Timeout, no solution within given time """ # +++++++++++++++++++++check for wrong input +++++++++++++++++++++++++++++ count = [0] * 6 try: for i in xrange(54): assert facelets[i] in colors count[colors[facelets[i]]] += 1 except Exception as e: return "Error 1" for i in xrange(6): if count[i] != 9: return "Error 1" fc = FaceCube(facelets) cc = fc.toCubieCube() s = cc.verify() if s != 0: return "Error %s" % abs(s) # +++++++++++++++++++++++ initialization +++++++++++++++++++++++++++++++++ c = CoordCube(cc) self.po[0] = 0 self.ax[0] = 0 self.flip[0] = c.flip self.twist[0] = c.twist self.parity[0] = c.parity self.slice[0] = c.FRtoBR / 24 self.URFtoDLF[0] = c.URFtoDLF self.FRtoBR[0] = c.FRtoBR self.URtoUL[0] = c.URtoUL self.UBtoDF[0] = c.UBtoDF self.minDistPhase1[1] = 1 # else failure for depth=1, n=0 mv = 0 n = 0 busy = False depthPhase1 = 1 tStart = time.time() # +++++++++++++++++++ Main loop ++++++++++++++++++++++++++++++++++++++++++ while True: while True: if depthPhase1 - n > self.minDistPhase1[n + 1] and not busy: if self.ax[n] == 0 and self.ax[n] == 3: # Initialize next move n += 1 self.ax[n] = 1 else: n += 1 self.ax[n] = 0 self.po[n] = 1 else: self.po[n] += 1 if self.po[n] > 3: while True: # increment axis self.ax[n] += 1 if self.ax[n] > 5: if time.time() - tStart > timeOut: return "Error 8" if n == 0: if depthPhase1 >= maxDepth: return "Error 7" else: depthPhase1 += 1 self.ax[n] = 0 self.po[n] = 1 busy = False break else: n -= 1 busy = True break else: self.po[n] = 1 busy = False if not (n != 0 and (self.ax[n - 1] == self.ax[n] or self.ax[n - 1] - 3 == self.ax[n])): break else: busy = False if not busy: break # +++++++++++++ compute new coordinates and new minDistPhase1 ++++++++++ # if minDistPhase1 =0, the H subgroup is reached mv = 3 * self.ax[n] + self.po[n] - 1 self.flip[n + 1] = CoordCube.flipMove[self.flip[n]][mv] self.twist[n + 1] = CoordCube.twistMove[self.twist[n]][mv] self.slice[n + 1] = CoordCube.FRtoBR_Move[self.slice[n] * 24][mv] / 24 self.minDistPhase1[n + 1] = max( getPruning( CoordCube.Slice_Flip_Prun, CoordCube.N_SLICE1 * self.flip[n + 1] + self.slice[n + 1] ), getPruning( CoordCube.Slice_Twist_Prun, CoordCube.N_SLICE1 * self.twist[n + 1] + self.slice[n + 1] ) ) # ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ if self.minDistPhase1[n + 1] == 0 and n >= depthPhase1 - 5: self.minDistPhase1[n + 1] = 10 # instead of 10 any value >5 is possible if n == depthPhase1 - 1: s = self.totalDepth(depthPhase1, maxDepth) if s >= 0: if (s == depthPhase1 or ( self.ax[depthPhase1 - 1] != self.ax[depthPhase1] and self.ax[depthPhase1 - 1] != self.ax[depthPhase1] + 3)): return self.solutionToString(s, depthPhase1) if useSeparator else self.solutionToString(s)
def to_face_cube(self) -> FaceCube: return FaceCube(self.face_str())