Ваша цель - написать идеального игрока для игры в Wythoff's Nim .
Правила Витоффа Нима
Ним из Wythoff - это детерминированная игра для двух игроков, в которую играют двумя кучами одинаковых фишек. Игроки чередуются ходами, в которых они выполняют одно из следующих действий:
- Удалите один или несколько жетонов из первой стопки.
- Убрать один или несколько жетонов из второй стопки.
- Удалите равное количество жетонов (один или несколько) как из первой, так и из второй стопки.
Конечно, стопки не могут быть отрицательными, но они могут равняться 0. Любой игрок, удаляющий последний счетчик, выигрывает в игре.
Для более геометрически мыслящих, вот эквивалентная формулировка игры, в которую вы можете играть в этом апплете . Одна королева начинается на некотором квадрате четверти бесконечной шахматной доски, угол которой находится внизу слева. Игроки поочередно перемещают королеву, которая движется как шахматная королева, но ограничена тремя направлениями:
- вниз
- Осталось
- По диагонали вниз и влево
Кто бы ни перемещает королеву в угол, побеждает.
Сопоставляя координаты королевы (с углом (0,0)
) с размерами соответствующих куч, легко увидеть, что обе игры одинаковы.
Идеальная игра
(Вы можете пропустить это, если знакомы с идеями идеальной игры и выигрышных ходов.)
Поскольку игра Нима Витоффа является конечной и детерминированной игрой, в ней есть понятие идеальной игры . Идеальный игрок - это стратегия, которая всегда выигрывает с теоретически выигранной позиции, то есть позиции, в которой существует стратегия, гарантирующая победу.
Чтобы быть выигрышной стратегией, достаточно двигаться, чтобы всегда перемещаться в теоретическую выигрышную позицию для игрока, который только что перешел, и, таким образом, игрок не пойдет дальше. Первая из этих выигрышных позиций (также называемых холодными позициями ) (0,0), (1,2), (2,1), (3,5), (5,3)
. См. Статью в Википедии для объяснения алгоритма, чтобы найти выигрышную стратегию для Wythoff's Nim, а также формулы для генерации выигрышных позиций.
Требования к программе
Написать программу или функцию принимает позицию в качестве входных данных и выводит выигрышный ход в виде позиции после этого хода. Побеждает несколько байтов.
Если выигрышного хода не существует, т. Е. Позиция является теоретической потерей, ваша программа должна указать это и проиграть.
Ваша программа должна быть запущена в течение разумного периода времени. Таким образом, экспоненциального рекурсивного поиска по дереву игр будет недостаточно. Если вы хотите предварительно вычислить и жестко закодировать стратегию, это нормально.
вход
Пара (i,j)
неотрицательных чисел, представляющих размеры стопки, каждое не более 99
. Это может быть два числа, кортеж, список или любой другой контейнер, который вы предпочитаете.
Выход
Напечатайте или выведите позицию после вашего перемещения, снова в виде двух чисел или контейнера. Это должен быть законный переход к выигрышной позиции. Если таких ходов несколько, любой подойдет, но только один.
Если выигрышного хода нет, вы должны указать это в выходных данных. Любой выход , как False
, None
, 0, или (-1,-1)
будет делать, пока это не правовая позиция, и то же самое для каждого входа проигравших.
Пример работает
f(5,0) = (0,0)
f(2,2) = (1,2) # Or (2,1) or (0,0)
f(1,2) = False
f(13,9) = (13,8) # Or (10,6)
f(10,6) = False
f(5,10) = (5,3)
f(25,30) = (8,13)
источник
Ответы:
Haskell,
167165 знаковАлгоритм неэффективен, но он все еще работает в течение секунды (хотя и не в интерактивной консоли) для входов <100.
Объяснение:
Список холодных позиций с учетом набора предыдущих холодных позиций представляет собой одну холодную позицию, за которой следует список холодных позиций с данной и предыдущими позициями (Неэффективность: эта позиция генерируется дважды).
Одна холодная позиция - это первая пара, так что из этой пары нет доступных холодных позиций (неэффективность: вместо этого мы должны искать из предыдущей пары)
Позиции, достижимые из пары, - это такие, в которых совпадают их первые элементы, совпадают их вторые элементы, совпадают их различия или чем меньше куча до удаления, тем больше куча после удаления.
(основной метод) Если кучи находятся в неправильном порядке, меняйте их местами. В противном случае, если первой холодной позицией, достижимой из позиции, является сама позиция, укажите сбой (в идеале
Maybe (Int,Int)
вместо этого следует вернуться ). Еще верните эту холодную позицию (Неэффективность: указанная пара ищется дважды. Хуже того, список холодных позиций генерируется дважды)источник
x@
изx@(a,b)?p=...
GolfScript (
6357 байт)Ожидает ввод от stdin в форме
[a b]
и оставляет вывод на stdout в этой форме или0
если это проигрышная позиция. Онлайн демообзор
вычисляет список холодных позиций (включая перевернутую версию
[b a]
для каждой холодной позиции[a b]
), используя свойство последовательности Beatty .Затем
?
ищет первую холодную позицию, удовлетворяющую блоку, созданномукоторые в основном проверяет , что позиция достижима из позиции ввода путем вычисления разности векторов , а затем проверить , что это либо
[0 x]
,[x 0]
или[x x]
для некоторыхx > 0
. ИМО , что тест является самыми умным битом:0|$
силы любого массива в одном из этих форматов в форму во[0 x]
время отображения[0 0]
к[0]
,[a b]
где ниa
ниb
находится0
в массив из трех элементов, и[-x 0]
или[-x -x]
с[-x 0]
. Затем(!*,1=
проверяет, что у нас есть[0 x]
.Наконец
0]0=`
делает запасной вариант и форматирование для вывода.источник
Pyth 57
58 61 62Попробуйте онлайн.
Очень похоже на другие ответы, но на этой странице википедии больше ничего не оставалось;) Волшебное число
39
- это количество холодных позиций со значениями <99
.Определяет функцию,
g
которую вы можете вызвать какg 30 25
. Возвращает[]
в случае неудачи,[(13,8)]
в случае успеха.объяснение
источник
s
приведен к int - сохраняет несколько символов/____1
.rZ39
можно заменитьU39
, используя одинарный диапазон. Точно так же вы можете заменитьr99)
наU99
.U
. Я должен действительно обновить объяснение: P@
пересечение наборов, если теперь его вторым аргументом является список. Это немного неловкоa
Javascript ES6 - 280 байт
Минимизированный
расширенный
Хороший и быстрый алгоритм. Работает в O (n), но будет работать в постоянное время, если бы не цикл сохранения байтов. Цикл реализован в виде рекурсивного инкремента, поэтому скрипт в конечном итоге завершится с ошибкой рекурсии для n в сотнях или тысячах. Использует то же свойство последовательности Битти, которое упоминает мистер Тейлор, но вместо того, чтобы вычислять последовательность, оно просто подходит к правильному термину (ам).
Работает правильно на всех входах теста и многих десятках, кроме того, что я тестировал.
Функция для вызова
f
. Возвращает массив в случае успеха и0
после отказа.источник
Perl 5 - 109 (с 2 флагами)
Использование:
Просто рассчитывает решение для каждого возможного ввода, а затем просто выполняет поиск.
источник