예제 #1
0
class SolutionStep(object):
    ROW = 0
    COL = 1

    def __init__(self, nonogram):
        self._uid = 1000
        self._idToIndex = {}
        self._nonogram = nonogram

        self._idToIndex[-1] = -1
        self._idToIndex[0] = 0

        self.row = [[self.__getIndex(x) for x in r] for r in nonogram.rows()]
        self.column = [[self.__getIndex(x) for x in c]
                       for c in nonogram.columns()]

        y_size, x_size = self.shape()
        self._sol = Solution(shape=(x_size, y_size))
        self.matrix = Matrix(x=x_size, y=y_size, default=SolutionCell())

    def __getIndex(self, value):
        self._uid = self._uid + 1
        index = LayoutIndex(value)
        self._idToIndex[index.id()] = index

        return index

    def index(self, uid):
        return self._idToIndex[int(uid)]

    def shape(self):
        return (len(self.column), len(self.row))

    def solution(self):
        return self._sol

    def row_layout(self, i):
        return self.row[i]

    def column_layout(self, i):
        return self.column[i]

    def row_lineup(self, i):
        return [x.v[self.ROW] for x in self.matrix.row(i)]

    def col_lineup(self, i):
        return [x.v[self.COL] for x in self.matrix.column(i)]

    def set_row(self, i, j, item):
        self.matrix.row(i)[j][self.ROW] = item
        self._sol.item(i, j).v = item.color()

    def set_col(self, i, j, item):
        self.matrix.col(i)[self.COL] = item
        self._sol.item(j, i).v = item.color()
예제 #2
0
파일: solution.py 프로젝트: zifter/nonogram
class Solution(SudokuDescr):
    def __init__(self, descr=None):
        SudokuDescr.__init__(self, matrix=descr.matrix)
        self.steps = []  # ((x, y), value)
        x, y = self.matrix.shape
        self.probability = Matrix(x=x, y=y, default_func=lambda ix, iy: Probability(self.values()))
        self.pending = [] # (x, y), value
        self.random = []

        indexes = set()
        for init in self.matrix:
            if init.v != 0:
                indexes.add(init.index())
                self.add_step(init.index(), init.v)

        new_pending = []
        for i in self.pending:
            if not i[0] in indexes:
                new_pending.append(i)

        self.pending = new_pending

    def probability_line(self, index):
        return [
            SolverMethod.belonged_box(index, self.probability, self.box_shape()),
            self.probability.row(index[1]),
            self.probability.column(index[0])
        ]

    def add_step(self, index, value):
        lines = self.probability_line(index)
        for l in lines:
            for i in l:
                if i.index() != index and i.v.erase(value, len(self.steps)):
                    self.add_pending(i.index(), i.v.value())

        self.probability.item_i(index).v.set(value, len(self.steps))
        self.steps.append((index, value))
        self.matrix.item_i(index).v = value

    def add_pending(self, index, value):
        self.pending.append((index, value))

    def add_random_choice(self, index, values):
        vs = copy(values)
        v = vs.pop()
        self.random.append((index,  vs, len(self.steps)))
        self.add_step(index, v)

    def rollback_random(self):
        # revert to 0 in matrix
        r = self.random.pop()
        while not r[1]:
            r = self.random.pop()

        rev = r[2]
        while rev != len(self.steps):
            s = self.steps.pop()
            self.matrix.item_i(s[0]).v = 0

        for item in self.probability:
            item.v.rollback(rev)

        self.pending = []
        self.add_random_choice(r[0], r[1])

    def process_pending(self):
        while self.pending:
            item = self.pending.pop()
            self.add_step(item[0], item[1])

    def is_done(self):
        x, y = self.matrix.shape
        return x*y == len(self.steps)