Вступление
На протяжении многих веков существовала определенная река, которая никогда не была нанесена на карту. Гильдия картографов хочет составить карту реки, однако, им так и не удалось добиться успеха - по какой-то причине все картографы, которых они отправили на карту реки, были съедены дикими животными в этом районе. Требуется другой подход.
Описание входа
Область представляет собой прямоугольную сетку ячеек длины m
и ширины n
. Ячейка в левом нижнем углу будет 0,0
, и ячейка в верхнем правом углу будет m-1,n-1
. m
и n
предоставляются на входе в виде кортежа m,n
.
С использованием методов географического зондирования на больших расстояниях было выявлено расположение островков вокруг реки. Размер островков (то есть, сколько клеток занимает остров) также были определены, но форма не имеет. Мы эту информацию в кортеже , s,x,y
где s
это размер острова, а также x
и y
являются х и у позиции одной конкретной ячейки этого острова. Каждый кортеж на входе разделен пробелами, поэтому вот пример ввода:
7,7 2,0,0 2,3,1 2,6,1 2,4,3 2,2,4 8,0,6 1,2,6 3,4,6
Чтобы проиллюстрировать более наглядно, вот входные данные на графике:
y 6|8 1 3
5|
4| 2
3| 2
2|
1| 2 2
0|2
=======
0123456
x
Описание выхода
Выведите карту, используя символы ASCII для представления частей области. Каждая клетка будет либо #
(земля), либо .
(вода). Карта должна соответствовать следующим правилам:
- Определение. Остров - это ортогонально смежная группа сухопутных ячеек, полностью ограниченная речными ячейками и / или границей района.
- Определение. Река - это ортогонально смежная группа водных клеток, которая полностью ограничена сухопутными клетками и / или границей области и не содержит "озер" (2x2 площади водных клеток).
- Правило . Карта должна содержать ровно одну реку.
- Правило . Каждая пронумерованная ячейка на входе должна быть частью острова, содержащего именно
s
ячейки. - Правило . Каждый остров на карте должен содержать ровно одну из пронумерованных ячеек на входе.
- Правило . Существует одна уникальная карта для каждого входа.
Вот вывод примера ввода:
#.#.##.
#....#.
#.##...
##..##.
###....
...##.#
##....#
Вот еще один вход и выход.
Входные данные:
5,5 3,0,1 1,4,1 2,0,4 2,2,4 2,4,4
Выход:
#.#.#
#.#.#
.....
###.#
.....
источник
javascript:(_=>{var t=Game.nurikabe().task,m=t.length,n=t[0].length,s=[m,n];for(var i=0;i<m;i++)for(var j=0;j<n;j++)if(t[i][j]>=0)s+=' '+[t[i][j],i,j];puzzleContainerDiv.insertAdjacentHTML('beforeend','<hr><tt style=color:red>'+s+'</tt><hr>')})();void(0)
Ответы:
C + PicoSAT ,
2345995952 байтаПопробуйте онлайн!
(Предупреждение: эта ссылка TIO представляет собой URL-адрес размером 30 килобайт, содержащий минимизированную копию PicoSAT 965, поэтому вы не сможете загрузить ее в некоторых браузерах, но она загружается как минимум в Firefox и Chrome.)
Как это устроено
Мы инициализируем решатель SAT с переменной для каждой ячейки (земли или воды) и только со следующими ограничениями:
Остальные ограничения сложно кодировать непосредственно в SAT, поэтому вместо этого мы запускаем решатель, чтобы получить модель, запускаем последовательность операций поиска в глубину, чтобы найти связанные области этой модели, и добавляем дополнительные ограничения следующим образом:
Используя преимущества инкрементного интерфейса к библиотеке PicoSAT, мы можем немедленно перезапустить решатель, включая добавленные ограничения, сохранив все предыдущие выводы, сделанные решателем. PicoSAT дает нам новую модель, и мы продолжаем повторять описанные выше шаги, пока решение не станет действительным.
Это удивительно эффективно; он решает 15 × 15 и 20 × 20 экземпляров за доли секунды.
(Спасибо Лопси за то, что он предложил эту идею интерактивного ограничения связанных областей в инкрементном SAT-решателе, некоторое время назад.)
Несколько больших тестовых примеров из головоломки-nurikabe.com
Случайная страница 15 × 15 сложных головоломок ( 5057541 , 5122197 , 5383030 , 6275294 , 6646970 , 6944232 ):
Случайная страница с 20 × 20 нормальными головоломками ( 536628 , 3757659 ):
источник
GLPK , (неконкурентный) 2197 байт
Это неконкурентная запись, так как
Я сохраню здесь еще не функциональную, но функциональную версию. В зависимости от обратной связи, я мог бы попытаться сократить это + добавить объяснение, если есть интерес. До сих пор имена ограничений служат документами на месте.
Основная идея заключается в кодировании ограничения «смежных островов» путем введения сохраненной переменной потока, которая имеет заранее заданный источник в месте подсказки. Решающая переменная
is_island
тогда играет роль размещаемых поглотителей. Минимизируя общую сумму этого потока, острова вынуждены оставаться соединенными в оптимуме. Другие ограничения довольно непосредственно реализуют различные правила. Что меня озадачивает, что мне все еще нужноisland_fields_have_at_least_one_neighbor
.Производительность этой формулировки не велика, хотя. При непосредственном поглощении всей сложности с большим количеством ограничений, решателю требуется около 15 секунд для примера 15 x 15.
Код (до сих пор не разгромлен)
Проблемные данные
5 х 5
7 х 7
15 х 15
использование
Были
glpsol
установлены, модель в виде одного файла (напримерriver.mod
), входные данные в отдельный файл (ы) (например7x7.mod
). Потом:Это плюс некоторое терпение распечатает решение в указанном формате вывода (вместе с «некоторым» выводом диагностики).
источник
Python 3 , 1295 байт
Это решение только для Python. Он не использует библиотеки и загружает плату через стандартный ввод. Дальнейшее объяснение впереди. Это моя первая попытка в таком большом гольфе. Внизу есть ссылка на закомментированный код без кода.
Попробуйте онлайн!
Посмотрите на код без гольфа .
источник