Befunge, 344 байта
&v>>>#p_:63p:43g`\!+v>/*53g+\01g:2%2*1-\2/!*63g+\0\:v
40$ v++!\`g14:p35:\<^2\-1*2%2p10::%4+g00:\g36\g35-1_v
#11^$_83p73v >1+:41g`!#v_$,1+:43g`!#v_@>->2>+00p+141^_
<p1^ vp< ^,g+7g36:<<<<1+55p36:<<<< ^1?0^#7g36g35*
8&p|!++!%9#2g+7g10\*!-g38g10!-g37:g00!!*<>3^
443>:!#v_>>1-::3%1-:53g+00p\3/1-:63g+01p^
^>^>>$#<"#"53g63g7+p41g53g-43g63g-+!#^_
Попробуйте онлайн!
Как упомянул @flawr в своем ответе на MATLAB, это может занять некоторое время, если размер поля любого нетривиального размера. На самом деле, довольно легко попасть в ситуацию, когда действительно не стоит пытаться дождаться его окончания, потому что вы, скорее всего, будете ждать до конца времени.
Чтобы понять, почему это происходит, полезно посмотреть, как выполняется программа, в одном из многочисленных «визуальных отладчиков» Befunge. Поскольку в Befunge данные и код - это одно и то же, вы увидите путь, который меняется с течением времени. Например, вот короткая анимация, показывающая, как может выглядеть часть бега по медленному пути.
Как только алгоритм решает совершить этот роковой поворот налево в нижней части границы поля, он по существу обрекает себя на целую жизнь бесцельного блуждания. С этого момента он должен пройти каждый возможный путь в этой огороженной области, прежде чем он сможет отступить и попытаться повернуть направо. И количество потенциальных путей в этих случаях может легко стать астрономическим.
Итог: если кажется, что это занимает много времени, возможно, хорошей идеей будет просто прервать выполнение и начать заново.
объяснение
Это в основном рекурсивный алгоритм, который пробует все возможные пути через поле, а затем раскручивает шаги, которые уже выполнялись, когда он застревал. Поскольку у Befunge нет понятия функций, о рекурсивной функции не может быть и речи, но мы можем эмулировать процесс, отслеживая состояние в стеке.
Это работает, заполняя стек потенциальными координатами, которым мы можем следовать. Затем мы извлекаем один набор из стека и проверяем, подходит ли он (то есть в диапазоне и не перекрывается ли существующий путь). Как только у нас будет подходящее место, мы записываем #
в игровое поле в этом месте и добавляем эти детали в стек на случай, если нам понадобится вернуться позже.
Затем мы помещаем дополнительные четыре набора координат в стек (в случайном порядке), указывая потенциальные пути, которые мы можем взять из этого нового местоположения, и возвращаемся к началу цикла. Если ни один из возможных путей не выполним, мы дойдем до той точки в стеке, где мы сохранили местоположение записанного #
нами, поэтому мы отменим этот шаг и продолжим пробовать потенциальные координаты с одного предыдущего шага.
Вот как выглядит код с выделенными различными компонентами:
Прочитайте ширину и высоту поля и нажмите начальные координаты вместе с 0
маркером типа, чтобы указать потенциальный путь, а не место возврата.
Проверьте места обратного отслеживания (обозначенные 1
маркером типа), которые возвращаются с помощью простой p
команды, поскольку они хранятся в точном формате, необходимом для записи пробела обратно в игровое поле.
Проверьте, находятся ли координаты внутри игрового поля. Если они находятся за пределами диапазона, отбросьте их из стека и вернитесь назад, чтобы попробовать следующие потенциальные координаты.
Если они находятся в диапазоне, получите следующие два значения из стека, который является местоположением предыдущего шага (требуется в следующем тесте).
Проверьте, вступят ли координаты в контакт с существующим сегментом пути. Местоположение предыдущего шага, очевидно, игнорируется этой проверкой.
Если все тесты пройдены успешно, напишите #
в игровое поле и проверьте, достигли ли мы места назначения.
Если у нас есть, запишите окончательный путь и выйдите.
В противном случае сохраните координаты в стек с 1
маркером типа для последующего возврата.
Это прерывается вычислением случайного числа, которое нам скоро понадобится.
Нажмите четыре потенциальных места назначения, которые могут быть достигнуты из текущего местоположения. Случайное число определяет порядок, в котором они выдвигаются, и, следовательно, порядок их следования.
Вернитесь к началу основного цикла и обработайте следующие значения в стеке.