Стратегии решения неравенства судоку?

Изюминкой классического решателя судоку, с которым я недавно столкнулся, является (довольно сумасшедший) судоку о неравенстве – это классическая головоломка-судоку с добавлением дополнительных условий, заключающихся в том, что в каждую ячейку добавлены условия неравенства.

Теперь мне удалось нацарапать обычный решатель судоку на Python (используя метод грубой силы), но я не могу понять, какие методы я бы использовал для решения этой проблемы. Я слишком много думаю или это намного сложнее, чем обычная головоломка?


person Nathaniel    schedule 12.04.2011    source источник
comment
Теория, стоящая за этим, заключается в том, что они дают вам числа, которые дают несколько ответов, если неравенства нет?   -  person cohensh    schedule 13.04.2011
comment
Вот это плюс случай, когда вам не дают цифр, а просто доску, полную неравенств.   -  person Nathaniel    schedule 13.04.2011


Ответы (2)


Это просто решение ограничений.

Если у вас есть доска судоку, то для каждой ячейки (i, j) у вас есть следующие ограничения:

board[i, j] in [1, 2, 3, 4, 5, 6, 7, 8, 9]
for each cell (a, j) where i != a: board[a, j] != board[i, j]
for each cell (i, b) where j != b: board[i, b] != board[i, j]

Для конкретных ячеек вы уже знаете их значение. Это действительно просто другое ограничение:

board[c1, c2] == 7

Вот и все. Средство проверки грубой силы может просто перебрать все возможные способы заполнения ячеек доски (особенно обращая внимание на первое ограничение) и проверить, выполняются ли эти ограничения. Если они все держат за эту заливку, то можно выводить доску. В противном случае это продолжается.

Если теперь вы разрешите неравенства для определенных позиций, вы можете использовать тот же самый алгоритм грубой силы. Это просто новая проверка, которую он должен сделать, прежде чем сказать, что доска заполнена правильно:

2 <= board[c3, c4] < 8

Это легко с помощью грубой силы, но также довольно просто с языком логического программирования, таким как Prolog, или библиотекой программирования с ограничениями, такой как Numberjack.

Вот версии всех вышеперечисленных ограничений в Numberjack (в порядке появления):

board[i, j] = Variable(1, 9)
# ... need to define all the board before you execute the following:
for a in xrange(1, 10):
    model.add(board[a, j] != board[i, j])
    model.add(board[i, a] != board[i, j])
model.add(board[c1, c2] == 7)
    model.add(board[c3, c4] < 8)
model.add(board[c3, c4] >= 2)

Это не идиоматично для реального использования решателя ограничений. В реальной жизни вместо того, чтобы указывать != по отдельности, вы бы использовали ограничение «Все они разные», AllDiff и т. д. Но Вы получаете идею.

person Devin Jeanpierre    schedule 12.04.2011
comment
Номерджек выглядит потрясающе! Спасибо, что познакомили меня с этим :) - person Nathaniel; 13.04.2011
comment
Как бы вы сказали, что это лучший способ добавить все мои ограничения в модель? У меня есть доска, представленная в виде матрицы: board = Matrix(N*N, N*N, 1, N*N, 'cell_') и модель sudoku с ограничениями, необходимыми для моделирования обычной игры в судоку. Должен ли я просто добавить целую кучу утверждений о неравенстве (например, sudoku.add(board[0][0] > board[0][1]) и т. д.) или есть более эффективный способ, который я упускаю? - person Nathaniel; 14.04.2011
comment
@Nathanial Честно говоря, я никогда не использовал Numberjack, я просто погуглил библиотеки решения ограничений Python и нашел их. Похоже, это будет что-то вроде for row in board: sudoku.add(AllDiff(row)) и то же самое для столбцов. - person Devin Jeanpierre; 14.04.2011

Вероятно, вы можете изменить решатель Питера Норвига, чтобы добавить эти ограничения.

person Community    schedule 13.04.2011
comment
РЕДАКТИРОВАТЬ: Ответил на неправильный комментарий. Но спасибо за подсказку — этот решатель великолепен. - person Nathaniel; 14.04.2011