Chomp - игра для двух игроков с настройкой прямоугольника фигур. Каждый игрок по очереди удаляет любую фигуру вместе со всеми фигурами над ней и справа от нее. Тот, кто берет нижний левый кусок, проигрывает. Достаточно легко доказать, что у первого игрока всегда есть выигрышный ход (за исключением прямоугольника 1 на 1); Найди это.
- Входными данными являются размеры прямоугольника (два числа)
- Выход - местоположение выигрышного хода (два числа)
- Если выигрышных ходов более одного, вы можете вывести любой из них.
Это код гольф; самый короткий код (любой язык) выигрывает.
Примеры
Примечание: выходы - только два числа; искусство ASCII ниже просто демонстрирует, что означают числа.
Ввод: 5 3 (индексы на основе 1, начиная с левого нижнего угла)
Выход: 4 3
XXX--
XXXXX
XXXXX
Вход: 4 4
Выход: 2 2
X---
X---
X---
XXXX
бонус
Вычтите 15 символов из вашего счета, если вы выводите все выигрышные ходы. Каждая пара чисел должна быть отделена новой строкой.
Ответы:
GolfScript, 82 (
10897 символов - 15 бонусов)Поскольку я не знал никакой эвристики, это решение выполняет исчерпывающий поиск в пространстве решений. Вы можете попробовать код онлайн . Хотя реализация очень эффективна, пространство поиска растет очень быстро с увеличением входных данных.
Примеры:
Как упоминалось выше, реализация не полагается на рекурсию, а посещает каждый узел пространства поиска только один раз. Ниже вы можете найти аннотированную версию кода, которая более подробно описывает строительные блоки.
Представление одной доски размером w * h задается списком из w чисел в диапазоне от 0 до h . Каждое число дает количество штук в соответствующем столбце. Таким образом, действительная конфигурация - это список, в котором числа не увеличиваются от начала до конца (при любом перемещении вы гарантируете, что все столбцы справа не больше, чем выбранный).
источник
Python
23, 141-15 = 126Минимаксный поиск методом грубой силы. Для каждого возможного хода мы рекурсивно видим, сможет ли противник выиграть после того, как мы сделаем этот ход. Довольно слабо играли в гольф; кто-то должен быть в состоянии сделать намного лучше. Это похоже на работу для APL.
win
это публичный интерфейс. Он берет размеры доски, преобразует ее в представление доски и передает ее вw
.w
это минимаксный алгоритм. Он принимает состояние доски, пробует все ходы, строит список, элементы которого соответствуют выигрышным ходам, и возвращает True, если список пуст. По умолчаниюf=print
построение списка имеет побочный эффект печати выигрышных ходов. Имя функции раньше имело смысл, когда она возвращала список выигрышных ходов, но затем я переместилnot
перед списком, чтобы сэкономить место.for r,p in enumerate(b)for c in xrange(p) if(r+c)
: Перебрать все возможные ходы.1 1
рассматривается как недопустимый шаг, немного упрощающий базовый вариант.b[:r]+[min(i,c)for i in b[r:]]
: Построить состояние доски после хода, представленного координатамиr
иc
.w(b[:r]+[min(i,c)for i in b[r:]],max)
: Проверьте, является ли новое состояние убыточным.max
это самая короткая функция, которую я смог найти, которая бы принимала два целочисленных аргумента и не жаловалась.f(r+1,c+1)
: Еслиf
печать, печатает ход. Что быf
это ни было , оно выдает значение для дополнения длины списка.not [...]
:not
возвращаетTrue
для пустых списков иFalse
для непустых.Оригинальный код Python 2, полностью безглобный, включая памятки для обработки гораздо больших входных данных:
Демо-версия:
источник
13x13
дубль2x2
и ты выиграл.Perl 6:
113108 символов - 15 = 93 баллаЭтот был жестким! Вот некэшированная версия, которая технически правильна, но займет очень много времени для нетривиальных вводов.
Он работает так же, как и реализация Python @ user2357112 (обоснуйте его / ее, я не мог бы понять это без его / ее работы!) За исключением того, что win () использует доску Chomp (массив) вместо ширины и длины. Может использоваться как:
Версия с памяткой, которая на самом деле может обрабатывать приличные входные данные (хотя и не оптимизирована для удобства чтения):
источник