Пример #1
0
    def set_constraints(self) -> Puzzle:
        # each house gets exactly one value from each set of literals
        for house in self.houses:
            for element_type in self.element_classes:
                literals_of_that_type = [l for l in self.literals if isinstance(l, element_type)]
                self._add_constraint(
                    sat_utils.one_of(comb(value, house) for value in literals_of_that_type)
                )

        # each value gets assigned to exactly one house
        for literal in self.literals:
            self._add_constraint(sat_utils.one_of(comb(literal, house) for house in self.houses))

        return self
Пример #2
0
    def solve_range(self):
        def comb(point, value):
            """Format how a value is shown at a given coordinate"""
            return intern(f'{point} {value}')

        values = ['W', 'B']
        all_coords = list(product(range(self.height), range(self.width)))

        for coord in all_coords:
            # Assign a "White" or "Black Box" value to each cell
            self.cnf += one_of(comb(coord, value) for value in values)

            # Rule: No two black squares are orthogonally adjacent.
            neighbor_coord = self.find_adjacency(coord)
            neighbor_dnf = [comb(coord, 'B')]
            for p in neighbor_coord:
                neighbor_dnf.append(comb(p, 'W'))
            self.cnf += from_dnf([neighbor_dnf, [comb(coord, 'W')]])

        for clue in self.clues:
            # for each clue (numbered cell), assign a valid permutation of black boxes
            permutation_len = len(clue.permutation_box)
            p_dnf = []
            for i in range(permutation_len):
                # different possible permutations for each clue
                temp = []
                for direction in clue.permutation_box[i].keys():
                    if clue.permutation_box[i][direction]:
                        temp.append(
                            comb(clue.permutation_box[i][direction], 'B'))

                for direction in clue.permutation_white[i].keys():
                    for cell in clue.permutation_white[i][direction]:
                        temp.append(comb(cell, 'W'))

                p_dnf.append(temp)

            # TODO: This from_dnf is so slow, maybe need some optimization
            self.cnf += from_dnf(p_dnf)

        possible_solution = solve_all(self.cnf)
        res = []
        for solution_facts in possible_solution:
            ans = deepcopy(self.board)
            box_list = []
            for fact_str in solution_facts:
                if fact_str[-1] == 'B':
                    row, col = eval(fact_str[:-2])
                    box_list.append((row, col))
                    ans[row][col] = 'B'

            if self.check_connectivity(box_list):
                # Rule: Verify the connectivity of all of the white cells
                res.append(deepcopy(ans))

        return res
Пример #3
0
        ' 9 7 4  1    6 2 8    1 43  6     59   1 3   97     8  52 7    6 8 4    7  5 8 2 ',
        '67 38      921   85    736 1 8  4 7  5 1 8 4  2 6  8 5 175    24   321      61 84',
        '27  15  8   3  7 4    7     5 1   7   9   2   6   2 5     8    6 5  4   8  59  41',
        '8 64 3    5     7     2    32  8  5   8 5 4  1   7  93    4     9     4    6 72 8',
        '  1 2 7   5     9    4      8   5    9           6   2  2        6     5     9 83',  # sudoku of 9 with only 17 digits http://www2.ic-net.or.jp/~takaken/auto/guest/bbs46.html 
        '1  3    7428      3        5  6   8  84537  6    4 5     482 6   5    7 612 9  3 ',
        '8          36      7  9 2   5   7       457     1   3   1    68  85   1  9    4  ',  # (was) hardest (35s)
        '1       2 9 4   5   6   7   5 9 3       7       85  4 7     6   3   9 8   2     1',  # (was) hard (28s) "easter monster"
        '     6    59     82    8    45        3        6  3 54   325  6                  ',  # hardest  norvig (188 sec, but not a sudoku)
]:

    cnf = []

    # each point assigned exactly one value
    for point in points:
        cnf += one_of(comb(point, value) for value in values)

    # each value gets assigned to exactly one point in each group
    for group in groups:
        for value in values:
            cnf += one_of(comb(point, value) for point in group)

    # add facts for known values in a specific puzzle
    for known in str_to_facts(given):
        cnf += basic_fact(known)

    # solve it and display the results
    result = facts_to_str(solve_one(cnf))
    show(given)
    print()
    show(result)
Пример #4
0

def beside(value1, value2):
    'The values occur side-by-side: blends1 & cat2 | blends2 & cat1 ...'
    return from_dnf([(comb(value1, i), comb(value2, j))
                     for i, j in zip(houses, houses[1:])] +
                    [(comb(value2, i), comb(value1, j))
                     for i, j in zip(houses, houses[1:])])


cnf = []

# each house gets exactly one value from each attribute group
for house in houses:
    for group in groups:
        cnf += one_of(comb(value, house) for value in group)

# each value gets assigned to exactly one house
for value in values:
    cnf += one_of(comb(value, house) for house in houses)

cnf += same_house('brit', 'red')
cnf += same_house('swede', 'dog')
cnf += same_house('dane', 'tea')
cnf += consecutive('green', 'white')
cnf += same_house('green', 'coffee')
cnf += same_house('pall mall', 'bird')
cnf += same_house('yellow', 'dunhill')
cnf += found_at('milk', 3)
cnf += found_at('norwegian', 1)
cnf += beside('blends', 'cat')