class Solver(ABC): def __init__(self, sequence): self.sequence = sequence # The sequence of the colors self.faces = Faces() # Datastructure to model the color constraint self.partial = dict() # Contains the partial solutions self.solutions = 0 self.steps = 0 @property @abstractmethod def starting_points(): pass def solve(self): """ Start solving from every start point """ for coord in self.starting_points: self._solve(coord, 0) return self.solutions, self.steps def _solve(self, coordinate, depth): """ Recursive step """ # Condition for termination: The cube is completed if depth == len(self.sequence) - 1: self.solution() return True self.steps += 1 color = self.sequence[depth] if self.constraints(coordinate, color): self.push(coordinate, color, depth) # Recursively solve for every neighbor for neighbor in neighbors(coordinate): if neighbor not in self.partial: # Only use free spaces self._solve(neighbor, depth + 1) self.pop(coordinate, color) def push(self, coordinate, color, depth): """ Step in: Go forward in the sequence and add the step to partial solution """ self.partial[coordinate] = (color, depth) self.faces.push(coordinate, color) def pop(self, coordinate, color): """ Step out: Go backwards in the sequence and remove the step from the partial solution """ self.faces.pop(coordinate, color) del self.partial[coordinate] def solution(self): """ Is called when a solution is found """ self.solutions += 1 human(self.partial) @abstractmethod def constraints(self, coordinate, color): """ Run checks to limit the recursion """ return True