Runs the Dancing Links/Algorithm X solver on the Sudoku.

        This code has been adapted from http://www.cs.mcgill.ca/~aassaf9/python/algorithm_x.html

        :return: List of lists with the same size as the input Sudoku, representing solutions.
        :rtype: list

def solve(self):
        """Runs the Dancing Links/Algorithm X solver on the Sudoku.

        This code has been adapted from http://www.cs.mcgill.ca/~aassaf9/python/algorithm_x.html

        :return: List of lists with the same size as the input Sudoku, representing solutions.
        :rtype: list

        """

        R, C = int(math.sqrt(len(self.sudoku))), int(math.sqrt(len(self.sudoku[0])))
        N = R * C

        X = ([("rc", rc) for rc in product(range(N), range(N))] +
             [("rn", rn) for rn in product(range(N), range(1, N + 1))] +
             [("cn", cn) for cn in product(range(N), range(1, N + 1))] +
             [("bn", bn) for bn in product(range(N), range(1, N + 1))])
        Y = dict()

        for r, c, n in product(range(N), range(N), range(1, N + 1)):
            b = (r // R) * R + (c // C)  # Box number
            Y[(r, c, n)] = [
                ("rc", (r, c)),
                ("rn", (r, n)),
                ("cn", (c, n)),
                ("bn", (b, n))]

        X, Y = self._exact_cover(X, Y)

        for i, row in enumerate(self.sudoku):
            for j, n in enumerate(row):
                if n:
                    self._select(X, Y, (i, j, n))

        for solution in self._solve(X, Y, []):
            grid = copy.deepcopy(self.sudoku)
            for (r, c, n) in solution:
                grid[r][c] = n
            yield grid