Введение
У вас есть несчастье застрять в бегущей машине на полосе препятствий. Все функции автомобиля не реагируют, за исключением системы рулевого управления, которая повреждена. Он может ехать прямо или поворачивать направо. Можно ли направить машину в безопасное место?
механика
Ваша машина начинается в верхнем левом углу карты 8x8 и пытается добраться до безопасности в правом нижнем углу. Автомобиль имеет ориентацию (первоначально вправо), измеряемую с шагом в 90 градусов. Автомобиль может выполнять одно из двух действий:
- Двигайтесь на одну клетку вперед или
- Поверните на 90 градусов по часовой стрелке, затем поверните на один квадрат вперед
Обратите внимание, что автомобиль не может поворачивать достаточно резко, чтобы выполнить поворот на 180 градусов на одном квадрате.
Некоторые из квадратов являются препятствиями. Если автомобиль входит в квадрат препятствий, он падает. Предполагается, что все, что находится вне поля 8х8, является препятствием, поэтому выезд с трассы равносилен краху.
Нижний правый квадрат является безопасным квадратом, который позволяет машине преодолеть полосу препятствий. Предполагается, что начальная и безопасная квадраты не являются препятствиями.
задача
Вы должны написать программу или функцию, которая принимает в качестве входных данных массив 8x8 (матрица, список списков и т. Д.), Представляющий полосу препятствий. Программа возвращает или печатает логическое значение, или что-то похожее правдивое. Если автомобиль может добраться до безопасного квадрата без сбоев (т. Е. Если карта разрешима), то в True
противном случае вывод получится False
.
счет
Стандартный код правил гольфа - победителем становится код с наименьшим количеством байтов.
Бонусы:
Если для разрешимой карты ваш код выводит правильную серию входов водителя, которые ведут автомобиль к безопасному квадрату, вычтите 10 процентных пунктов из вашей оценки. Примерным форматом вывода может быть
SRSSR
(с указанием Straight, Right, Straight, Straight, Right). Этот вывод заменит стандартныйTrue
вывод.Если для неразрешимой карты выходные данные вашего кода будут различаться между ситуациями, когда сбой неизбежен, и ситуациями, в которых возможно объездить полосу препятствий навсегда, вычтите 10 процентных пунктов из вашей оценки. Примером может быть вывод,
Crash
если авария неизбежна, илиStuck
если автомобиль застрял на полосе препятствий навсегда. Эти выходы заменили бы стандартныйFalse
вывод для неразрешимой карты.
пример
Если программе дан массив 8x8, такой как этот:
[[0, 0, 0, 0, 0, 1, 0, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 0, 0],
[0, 1, 0, 1, 0, 0, 0, 0],
[0, 0, 1, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 1, 0],
[0, 0, 0, 0, 0, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 0]]
Это будет интерпретироваться как карта с черными квадратами, обозначающими препятствия:
И возможное решение может быть:
Поскольку решение существует, программа должна вернуть / напечатать True
для этой карты. Последовательность ходов , показанная здесь SSSSRSRRRSRSSRRRSSRSSS
.
Crash
иStuck
. Они здесь из-за того, как долго они. Строка 2 заполнена, все остальное пусто ->Crash
. Строка 7 заполнена, все остальное пусто ->Stuck
Ответы:
JavaScript (ES6) - 122
124148байт162172178187190193208Большое спасибо Optimizer и DocMax за полезные советы по улучшению этого кода:
Возвращает
true
(истинно) для разрешимого иfalse
(ложно) для неразрешимого.На сегодняшний день работает только в Firefox благодаря возможностям JavaScript 1.7.
Тестовая доска
источник
D=(x,y,d,t,a)=>!t[i=x+y*8+d*64]&&(t[i]=1,x+=d==0?1:d==2?-1:0,y+=d==1?1:d==3?-1:0,x==7&&y==7||!((x|y)&~7||a[y][x])&&G(x,y,d,t,a));G=(x,y,d,t,a)=>D(x,y,d,t,a)||D(x,y,d+1&3,t,a);F=a=>G(0,0,0,[],a)
.D=d=>!t[i=x+y*8+d/4]&&(t[i]=1,x+=d?d^2?0:-1:1,y+=d^1?d^3?0:-1:1,x==7&&y==7||!((x|y)&~7||b[y][x])&&G(x,y,d));G=(X,Y,d)=>D(d,x=X,y=Y)||D(d+1&3,x=X,y=Y);F=a=>G(0,0,0,b=a,t={})
- Проверено.[[0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0]]
. Это должно дать ложь.x
иy
оба Глобал, вы не можете запустить два testcases перед загрузкой страницы ...x+=d?d^2?0:-1:1
сx+=d&1?0:1-d
иy+=d^1?d^3?0:-1:1
сy+=d&1&&2-d
.Python 2 - 123
125 133 146 148 150 154 160True
в случае успеха,False
в случае неудачи.Вы должны предоставить вход как
f(b=var_containing_board)
.Лямбда-версия - 154
Возвращает
0
(ложно) для неудачи,True
для успеха.Спасибо Уиллу и Брэндону за то, что они сделали функцию короче лямбды. Также для добавления дополнительной горизонтальной прокрутки: D
Спасибо xnor за превосходную битовую биту и логику!
Редактировать примечание: я достаточно уверен, что
b[y][x]
никогда не будет выполнен при выходе за пределы диапазона. Поскольку мы за пределами доски, проверка историиs in c
будетFalse
. Тогда проверка границы(x|y)&8
будет8
. Тогда python даже не будет проверять последнее значение,==
потому что первые два уже различны.источник
x|y>7or
работает, ноx|y<0or
не ...0o
.C (GNU-C), 163 байта * 0,9 = 146,7
#C (GNU-C), 186 байт * 0,9 = 167,4Моя новая версия использует целое число со знаком, а не без знака. Раньше я боялся подписанного правого сдвига, но понял, что знаковый бит - это квадрат ворот, и не важно, что произойдет после этого.
Функция принимает массив битов (единицы представляют собой блокированные квадраты) в виде 64-битного целого числа. Биты расположены от младшего к старшему так же, как вы читаете книгу. Возвращает -1 для аварии, 0 для движения навсегда или 1 для выхода в правый нижний угол.
Тестовая программа
Выход
Преобразователь массива в шестигранник Python:
источник
memset(&M,~1,8)
(15 символов) наM=~(-1ULL/255)
(14 символов).P(0x00fefefefefefefe);
= (Должен быть прямым выстрелом в верхний правый угол, один поворот, прямо в угол. То же самое дляP(0x00eeeeeeeeeeeeee);
(тупик на 4-м столбце). Я не думаю, что вам нужно назначатьa
изначально.0x7f7f7f7f7f7f7f00
. Также необходимо выполнить инициализацию,a
потому что позже она изменяется только путем ORing в дополнительных битах, поэтому я не могу позволить себе изначально установить нежелательный бит.Питон, 187
213207 символов, 10% бонус за путь печати
На входе теста он находит немного другой путь:
SSSSRSRSRRSSRSSRRSRSSRSSSSS
Общий подход заключается в том, чтобы сначала превратить ввод в пробелы и
o
s. Пробелы имеют шестнадцатеричный код20
, поэтому все четыре младших бита не установлены.o
имеет шестнадцатеричный код6F
, поэтому младшие четыре бита все установлены.Граница
o
s размещена вокруг доски, поэтому нам не нужно беспокоиться о плохих показателях.Когда мы идем по доске, мы используем биты в каждом тайле, чтобы увидеть, разрешено ли нам проходить, когда мы идем с этой стороны. Таким образом, мы избегаем бесконечных циклов. Недостаточно иметь единственное логическое значение на плитку, так как направление выхода зависит от направления входа, поэтому плитки можно посетить дважды.
Затем мы делаем рекурсивный поиск безопасного пути.
источник
9
на местеw=len(b[0])+1
, и т.д.?p==79
наp-79
. Я получил синтаксическую ошибку, делающую это в обоих направлениях без пробела передelse
. Я думаю, что этот трюк работает только сif
.-~x
==,x+1
но оба унарных оператора имеют более высокий приоритет, чем умножение, деление и модуль! Так(d+1)%4
может быть-~d%4
! Это также будет работать,x-1
но просто использовать~-x
вместо этого.Javascript -
270 - 20% = 216262 - 20% = 210 байтовТак как должно быть хотя бы одно решение, которое зарабатывает оба бонуса (и не приводит к нелепой глубине стека;) ...
уменьшенная:
Expanded:
v
является хеш-таблицей с ключами, которые являются тройками состояний,(x,y,d)
соответствующими координате (x, y) и направлению входаd
. У каждого ключа есть связанное значение, которое представляет собой строкуS
(прямое) иR
(повернуть направо) ходов, необходимых для достижения состояния, представленного ключом.Код также поддерживает стек троек (в переменной
n
), которые еще не были обработаны. Стек изначально содержит только тройку (0,0,0), соответствующую состоянию, в котором автомобиль стоит прямо в ячейке (0,0). Во внешнем циклеfor( S = ... )
подпрограмма проверяет, остаются ли необработанные тройки. Если это так, то каждый необработанный триплет проходит по внутреннему циклуn.map( ...
.Внутренний цикл делает пять вещей:
K
(застрял), поскольку мы нашли по крайней мере один цикл, в котором автомобиль может продолжать вращаться вечно, не разбиваясь.v
) и в стек необработанных триплетов (m
) для следующего прохода внешнего циклаv
, его значение устанавливается равным значению исходного состояния (последовательности ходов) плюсR
илиS
на основе текущего ходаx
иy
есть7
, значение исходного состояния (последовательность ходов, предпринятых для достижения исходного состояния) копируетсяS
, поскольку эта последовательность ходов является решением проблемыПосле завершения внутреннего цикла
n
(стек) заменяется наm
(новый стек).После завершения внешнего цикла (новые состояния не были достигнуты), функция возвращает свой вывод. Если ячейка (7,7) была достигнута,
S
будет содержать последовательность ходов, ведущих к этой ячейке, и это выводится. Если ячейка не была достигнута,S
будет пустой строкой, и процедура переходит к выводуO
, который будет содержатьK
(застрял), если и только если был найден цикл, илиC
(сбой), если автомобиль неизбежно потерпит крах.источник
Python 339 - 10% = 305 байт
Я использовал рекурсивный поиск в глубину, который был прерван в случае успеха через
exit
. Также печатание пути на удачу в виде00001010101010101010101110100111001000
,0
прямо,1
направо. Ответ будет длиннее, чем оптимальный, так как он в глубину. Я уверен, что некоторые оптимизации алгоритма могут немного снизить количество байтов.источник
a
«Sfor
цикла. Вам также не нужны пробелы вокруг операторов, например(v+1) % 4
->(v+1)%4
. Вы также можете объединить несколько операторов в одну строку, используя,;
если нетif
илиfor
, и т. Д. В строке, напримерc(l+"0");c(l+"1")
. Некоторые другие гольфы:x,y,v=0,0,2
,x|y>7 or x|y<0
,x==y==7
. Удачи :)