Если вы не знаете, что такое Ханойская башня , я кратко объясню: есть три стержня и несколько дисков, каждый из которых имеет свой размер. В начале все диски находятся на первой башне в отсортированном порядке: самый большой внизу, самый маленький сверху. Цель состоит в том, чтобы перенести все диски на третий стержень. Звучит легко? В этом и заключается подвох: вы не можете поместить диск поверх диска, который меньше другого диска; вы можете держать только один диск в руке за раз, чтобы переместить их на другой стержень, и вы можете поместить диск только на стержни, а не на стол, подлый ублюдок.
Пример решения ascii:
A B C
| | |
_|_ | |
__|__ | |
A B C
| | |
| | |
__|__ _|_ |
A B C
| | |
| | |
| _|_ __|__
A B C
| | |
| | _|_
| | __|__
Вызов
Есть три стержня, называемые A, B и C. (Вы можете также назвать их 1,2 и 3 соответственно, если это помогает). В начале все n дисков находятся на стержне A (1).
Ваша задача состоит в том, чтобы проверить решение для Ханойской башни. Вам нужно убедиться, что:
- В конце концов все n дисков находятся на штоке C (3).
- Для любого данного диска в любом данном состоянии под ним нет меньшего диска.
- Нет очевидных ошибок, таких как попытка извлечь диски из пустого стержня или перемещение дисков в несуществующие стержни.
(решение не должно быть оптимальным.)
вход
Ваша программа получит два входа:
- Количество дисков n (целое число)
Выполняемые ходы, которые будут состоять из набора кортежей: (башня, из которой будет взят самый верхний диск в данный момент), (башня, в которую будет доставлен этот диск), где каждый кортеж относится к ходу. Вы можете выбрать, как они представлены. Например, что-то вроде следующих способов представления решения для n = 2, которые я нарисовал в ascii выше. (Я буду использовать первый в тестовых случаях, потому что это легко для глаз):
"A-> B; A-> C; B-> C"
[( "А", "В"), ( "А", "С"), ( "В", "С")]
[(1,2), (1,3), (2,3)]
"ABACBC"
[1,2,1,3,2,3]
Выход
Правда, если условия, которые можно найти под «вызовом», держатся.
Ложь, если они этого не делают.
Тестовые случаи:
Правда:
n=1, "A->C"
n=1, "A->B ; B->C"
n=2, "A->B ; A->C ; B->C"
n=2, "A->C ; C->B ; A->C ; B->C"
n=2, "A->C ; A->B ; C->B ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C ; B->C"
Ложь:
3-й предложен @MartinEnder, 7-й - @Joffan
n=1, "A->B"
n=1, "C->A"
n=2, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=2, "A->B ; A->C ; C->B"
n=2, "A->C ; A->B ; C->B ; B->A"
n=2, "A->C ; A->C"
n=3, "A->B ; A->D; A->C ; D->C ; A->C"
n=3, "A->C ; A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->B ; B->C ; B->A ; B->C ; A->C"
n=3, "A->C ; A->B ; C->B ; A->C ; B->A ; B->C ; C->B"
n=4, "A->B ; A->C ; B->C ; A->B ; C->A ; C->B ; A->B ; A->C ; B->C ; B->A ; C->A ; B->C ; A->B ; A->C"
n=4, "A->B ; A->B ; A->B ; A->C ; B->C ; B->C ; B->C"
Это код-гольф , выигрывает самое короткое решение. Применяются стандартные правила и лазейки. Аккумуляторы не включены.
A=1
,B=2
,C=3
и т.д.)?A->A
?moving discs to nonexistant rods.
это, конечно, да, этоD
Ответы:
Сетчатка ,
8480 байт-5 байт благодаря Мартину Эндеру
Попробуйте онлайн! (плюс 5 байтов для построчных тестов)
Код имитирует полноценную игру.
ACABCBACBABCAC~~~
.~~~
означает три диска.ACABCBACBABCAC ~~~ ~~ ~ABC
.Сначала стержень A имеет все 3 диска, а стержни B и C пусты.
В нашем примере, после первого шага, текст будет выглядеть следующим образом :
~CABCBACBABCAC ~~~ ~~ABC
.ABCBACBABCAC ~~~ ~~AB ~C
.источник
Сетчатка ,
167165157150123 байтаЭто полностью похоже на проблему, которая должна быть решена с помощью одного регулярного выражения ... (несмотря на то, что заголовок говорит "Retina", это просто ванильное регулярное выражение .NET, соответствующее допустимым входным данным).
Формат ввода - это список инструкций формы
AB
, за которыми следуетn
одинарная цифра1
. Там нет разделителей. Выходные данные1
действительны и0
недействительны.Попробуйте онлайн! (Первые два символа включают набор тестов, разделенных переводом строки.)
Альтернативное решение с тем же количеством байтов:
Это может возможно быть сокращено путем использования
1
,11
и111
вместо того , чтобыA
,B
и ,C
но я должен буду смотреть на это позже. Также может быть короче разделить программу на несколько этапов, но где проблема в этом? ;)объяснение
Это решение интенсивно использует балансировочные группы .NET. Полное объяснение см. В моем посте о переполнении стека , но суть в том, что группы захвата в .NET являются стеками, где каждый новый захват выталкивает другую подстроку и где также можно снова извлечь из такого стека. Это позволяет вам считать различные количества в строке. В этом случае это позволяет нам реализовать три стержня непосредственно как три разные группы захвата, где каждый диск представлен захватом.
Для перемещения дисков между стержнями мы используем странную причуду
(?<A-B>...)
синтаксиса. Как правило, это извлекает захват из стекаB
и помещает в стекA
строку между этим извлеченным захватом и началом этой группы. Таким образом,(?<A>a).(?<B-A>c)
противabc
будет оставитьA
пустым иB
сb
(в отличие отc
). Тем не менее, из-за взгляда переменной длины .NET возможно захватывать(?<A>...)
и(?<B-A>...)
перекрывать друг друга. По какой-то причине, если это так, пересечение двух групп выдвигается наB
. Я подробно описал это поведение в «расширенном разделе» о балансировке групп в этом ответе .На регулярное выражение. Стержни
A
,B
иC
соответствуют группам3
,4
и5
в регулярном выражении. Начнем с инициализации стержняA
:Так, например, если ввод заканчивается на
111
, группа 3 / rodA
теперь будет содержать список снимков[111, 11, 1]
(верхняя часть справа).Следующий бит кода имеет следующую структуру:
Каждая итерация этого цикла обрабатывает одну инструкцию. Первое чередование вытягивает диск из данного стержня (во временную группу), второе чередование помещает этот диск в другой заданный стержень. Через некоторое время мы увидим, как это работает и как мы гарантируем, что движение действительно.
Сначала снимем диск со стержня источника:
Это использует странное поведение пересечения групп, которое я описал выше. Обратите внимание, что группа
3
,4
и5
всегда будет содержать подстроки1
s в конце строки, длина которой соответствует размеру диска. Теперь мы используем,(?<1-N>.+)
чтобыN
вытолкнуть верхний диск из стека и поместить пересечение этой подстроки с совпадением.+
в стек1
. Так как.+
всегда обязательно охватывает весь снятый захватN
, мы знаем, что это просто перемещает захват.Затем мы помещаем этот диск из стопки
1
в стопку, соответствующую второму стержню:Обратите внимание, что нам не нужно очищать стек
1
, мы можем просто оставить диск там, так как мы поместим новый поверх, прежде чем снова использовать стек. Это означает, что мы можем избежать(?<A-B>...)
синтаксиса и просто скопировать строку с помощью(\1)
. Чтобы убедиться, что ход действителен, мы используем негативную перспективу(?!\N)
. Это гарантирует, что с позиции, где мы хотим сопоставить текущий диск, невозможно сопоставить диск уже в стекеN
. Это может произойти, только если a)\N
никогда не совпадет, потому что стек полностью пуст или b)the disc on top of stack
Nis larger than the one we're trying to match with
\ 1`.Наконец, все, что осталось, - это убедиться, что а) мы сопоставили все инструкции и б) стержни
A
иB
они пусты, чтобы все диски были перенесеныC
.Мы просто проверяем, что ни то, ни другое
\3
не\4
может соответствовать (что имеет место только в том случае, если оба являются пустыми, потому что любой фактический диск будет соответствовать), и что мы можем затем сопоставить,1
чтобы мы не пропустили никаких инструкций.источник
Java "только"
311 272 263 261 260 259256 байтСохранено
39бесчисленных байтов благодаря @Frozn, который заметил более старую функцию отладки, а также некоторые хитрые уловки игры в гольф.Гольф версия
безрассудный с объяснениями и красивыми печатными стопками на каждом шагу
Версия без гольфа имеет функцию, которая будет распечатывать, как выглядят стеки на каждом этапе, так ...
источник
System.out.println(Arrays.toString(s))
?&&
на&
.Python 2,
186167158135127115110102 байтаПринимает ввод на STDIN в следующем формате:
То есть кортеж Python из числа дисков и список кортежей Python из
(from_rod,to_rod)
. Как и в Python, окружающие скобки являются необязательными. Стержни с нулевой индексацией.Например, этот тестовый пример:
будет дано как:
Если решение действительно, ничего не выводит и завершает работу с кодом выхода 0. Если оно недопустимо, генерирует исключение и завершается с кодом выхода 1. Бросает,
IndexError
если переходит на несуществующий стержень или пытается снять диск с диска. стержень, на котором нет дисков, a,ZeroDivisionError
если диск помещен поверх меньшего диска, или a,NameError
если на конце остались первые или вторые стержни дисков.Сохранено 13 байт благодаря @KarlKastor!
Сохранено 8 байт благодаря @xnor!
источник
Python 2.7,
173158138130127123 байта:Принимает ввод через стандартный ввод в формате
(<Number of Discs>,<Moves>)
где<Moves>
задан как массив, содержащий кортежи, соответствующие каждому ходу, каждый из которых содержит пару целых чисел, разделенных запятыми. Например, контрольный пример:данный в посте будет дан как:
к моей программе. Выводит,
IndexError
если 3-е условие не выполнено, a,NameError
если 2-е условие не выполняется, иFalse
если 1-е условие не выполняется. В противном случае выводитTrue
.источник
Y
никогда не определяется в вашем коде (я думаю, что это должен быть J) иU[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]
короче на 3 символа, чтоstmt1 if cond else stmt2
Y
переменную, чтобы поднять,NameError
когда 2-е условие не выполняется. Если бы я изменить ,Y
чтобыJ
, тоNameError
не будет поднят. По этой причине, я не могу сделать ,U[J]+=[Y,[U[K].pop()]][U[J]<[1]or U[K]<U[J]]
потому что это подняло бы наNameError
все время , а не только , когда второе условие не выполнено.VBA,
234217213196 байтФормат ввода для ходов - строка с четным числом цифр (012). Вызов в электронной таблице, = H ([количество дисков], [переместить строку])
Массив A содержит положение стержня различных дисков. Ход просто обновляет первое вхождение номера стержня «От» в номер стержня «Кому». Если вы столкнулись с первым стержневым диском «To» или без «стержневого диска« From »», это неверный ход. Общее «значение стержня» A содержится в L, которое должно заканчиваться на 2N. Ошибки накапливаются как отрицательный счет в E.
Как и в других решениях, «перемещение» диска из башни в ту же башню не запрещено. Я мог бы запретить это еще на 6 байтов.
Полученные результаты
Результат функции в первом столбце (последний случай n = 3 - это мое добавление с использованием дополнительного стержня).
источник
php, 141 байт
Скрипт командной строки, принимает входные данные в качестве высоты, а затем ряд индексов массива (0 проиндексированных), например, 1 0 2 или 2 0 1 0 2 1 2 для 1 или 2 кратчайших тестовых примеров высоты.
Отголосок 1 на истинных случаях и ничего на ложных.
Дает 2 уведомления и 1 предупреждение, поэтому необходимо запустить их в среде, которая их заставляет замолчать.
источник
JavaScript (ES6), 108
Формат ввода: функция с 2 аргументами
Вывод: вернуть 1, если все в порядке, 0, если недействительно, исключение, если не существует стержня
Менее гольф и объяснил
Примечание к тесту : первая строка функции «Тест» необходима для преобразования входного формата, заданного в вопросе, во ввод, ожидаемый моей функцией.
источник