Example #1
0
    def _color_code(cls, cell):
        if is_color_cell(cell):
            single_colors = two_powers(cell)
            if len(single_colors) > 3:  # allow two and three colors
                # multiple colors
                return UNKNOWN

        return cell
Example #2
0
    def __init__(self, value, renderer, colored=False):
        super(GridCell, self).__init__()

        self.renderer = renderer
        self.colored = colored
        if self.colored:
            self.value = tuple(two_powers(value))
        else:
            self.value = value
Example #3
0
    def match(self, word):
        one_color_word = []

        for letter in word:
            letter = two_powers(letter)
            if len(letter) == 1:
                letter = letter[0]

            one_color_word.append(letter)

        return super(NonogramFSMColored, self).match(one_color_word)
Example #4
0
    def test_random(self):
        for i in range(100):
            n = random.randint(1, 10**9)

            factors = two_powers(n)
            assert len(factors) > 0
            # factors are unique
            assert len(set(factors)) == len(factors)
            assert sum(factors) == n

            for f in factors:
                b = bin(f)
                assert b == '0b1' + '0' * (len(b) - 3)
Example #5
0
    def block_ranges_left(cls, description, line):
        """
        Shift the blocks to the left and find valid start positions
        """
        # line_colors = set(block.color for block in description)
        allowed_colors_positions = defaultdict(list)
        for index, cell in enumerate(line):
            for single_color in two_powers(cell):
                allowed_colors_positions[single_color].append(index)

        min_start_indexes = cls.calc_block_sum(description)[1:]
        LOG.debug(min_start_indexes)

        for block_index, block in enumerate(description):
            color = block.color
            # do not do `zip(desc, min_indexes)` because min_indexes changes
            min_index = min_start_indexes[block_index]

            rang = [
                index for index in allowed_colors_positions[color]
                if index >= min_index
            ]

            if not rang:
                raise NonogramError(
                    'The #{} block ({}) cannot be placed'.format(
                        block_index, block))

            min_index_shift = min(rang) - min_index
            if min_index_shift > 0:
                LOG.info(
                    'Minimum starting index for block #%i (%r) updated: %i --> %i',
                    block_index, block, min_index, min_index + min_index_shift)

                min_start_indexes[block_index:] = [
                    i + min_index_shift
                    for i in min_start_indexes[block_index:]
                ]

            yield rang

        LOG.debug(min_start_indexes)
Example #6
0
 def _types_for_cell(cls, cell):
     return two_powers(cell)
Example #7
0
    def starting_solved(cls, description, line):
        """
        Trim off the solved cells from the beginning of the line.
        Also fix the description respectively.

        Return the pair (number of solved cells, number of solved blocks)
        """
        space = SPACE_COLORED

        block_index = 0
        last_block = len(description) - 1

        pos = 0
        last_pos = len(line) - 1

        while pos <= last_pos:
            # skip definite spaces
            if line[pos] == space:
                pos += 1
                continue

            cell = line[pos]
            cell_colors = two_powers(cell)
            if len(cell_colors) > 1:
                break

            color = cell_colors[0]

            if block_index > last_block:
                raise NonogramError('Bad block index {} '
                                    'for description {!r}'.format(
                                        block_index, description))

            block = description[block_index]
            if color != block.color:
                raise NonogramError(
                    'Color {!r} at the position {!r} of the line {!r}'
                    'does not match the color of the corresponding block {!r} '
                    'in description {!r}'.format(color, pos, line, block,
                                                 description))

            size = block.size
            if size == BlottedBlock:

                end_pos = pos + 1
                while end_pos <= last_pos and line[end_pos] == color:
                    end_pos += 1

                if end_pos <= last_pos:
                    cell_colors = two_powers(line[end_pos])
                    # can't say definitely whether the blotted block ends here
                    if color in cell_colors:
                        # the partially solved blotted block can be reduced to one cell
                        pos = end_pos - 1
                        break

                pos = end_pos
                block_index += 1

            else:
                if pos + size > last_pos + 1:
                    raise NonogramError(
                        'The {}-th block {!r} cannot be allocated in the line {!r}'
                        .format(block_index, block, line))

                if line[pos:pos + size] != [color] * size:
                    break

                if block_index < last_block:
                    next_block = description[block_index + 1]
                    if next_block.color == color:
                        try:
                            if line[pos + size] != space:
                                break
                        except IndexError:
                            raise NonogramError(
                                'The next ({}-th) block {!r} '
                                'cannot be allocated in the line {!r}'.format(
                                    block_index + 1, next_block, line))
                pos += size
                block_index += 1

        return pos, block_index
Example #8
0
    def test_round_trip(self):
        for i in range(100):
            n = random.randint(1, 10**9)

            factors = two_powers(n)
            assert from_two_powers(factors) == n
Example #9
0
 def test_simple(self):
     assert two_powers(42) == (2, 8, 32)
     assert two_powers(103) == (1, 2, 4, 32, 64)
Example #10
0
 def test_one(self):
     assert two_powers(1) == (1, )
Example #11
0
 def test_zero(self):
     assert two_powers(0) == ()
Example #12
0
    def is_solved(cls, description, line):
        if any(len(two_powers(cell)) > 1 for cell in line):
            return False

        return BlottedBlock.matches(description, line)