C #, 600 574 байт
Повна програма, приймає вхід від STDIN, вихід на STDOUT.
Редагувати: в обробці обгорткою виникла помилка (не зламалася жодна з наведених тестових випадків), яка додала б 1 байт, тому я зробив трохи більше гольфу для компенсації.
using Q=System.Console;struct P{int p,d;static void Main(){string D="",L;int w=0,W=0,o,n=1;for(;(L=Q.ReadLine())!=null;D+=L)w=(o=(L+="X").Length+1)>w?o:w;for(;W<D.Length;)D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0));P[]K=new P[W*6];var T=new string[W*6];P c=K[o=0]=new P{p=D.IndexOf('S')};for(System.Action A=()=>{if(c.p>=0&c.p<W&System.Array.IndexOf(K,c)<0&&D[c.p]%8>0){T[n]=T[o]+L;K[n]=c;n=D[c.p]==69?-n:n+1;}};o<n;o++){c=K[o];L="R";c.d=++c.d%6;A();L="L";c.d=(c.d+4)%6;A();L="F";c=K[o];c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6];A();}Q.WriteLine(n>0?"Invalid maze!":T[-n]);}}
Починається з читання на карті, додавання (
до кожного рядка, щоб він знав, де він закінчується, і може повернутися назад і додати в набір пробілів, щоб зробити карту прямокутною та з рядом пробілів уздовж правої сторони (це економить ми робимо обгорткові чеки, як буде пояснено нижче). Він визначає ширину прямокутника в якийсь момент цього і визначає загальну довжину Карти.
Далі він ініціалізує все для пошуку в першу чергу. Створено два масиви biggish, один для зберігання всіх станів, які нам потрібно дослідити, під час пошуку, інший для запису маршруту, який ми пройшли, щоб дістатися до кожного штату. Початковий стан додається до відповідного масиву, в якому вказівники голови та хвоста попередньо встановлені вище. Все є 1-індексованим.
Потім ми повторюємо, поки хвіст не вріжеться в голову, або, принаймні, схоже , врізався в голову. Для кожного стану, який ми відвідали, ми намагаємося додати новий стан у тому самому положенні, де ми повертаємося вліво або вправо, а потім у той, де ми рухалися вперед. Напрямки індексуються з початковим напрямком (за замовчуванням до0
) відповідає "вгору-вліво".
Коли ми намагаємося встановити чергу, стан перевіряється, але не перевіряється загортанням через стовпчики пробілів на правій стороні, на яких позначено "чи ми можемо бути тут?" перевірити (вам не дозволяється знаходитись у пробілах). Якщо стан у черзі, ми перевіряємо, чи знаходиться він у E
комірці, і якщо він є, встановлюємо голову черги як мінус, що призводить до виходу основного циклу, і повідомляє друку останнього рядка програми відповідний маршрут, а не повідомлення про помилку (яке показує, якщо у нас не вистачає штатів для розширення (хвіст врізається в голову)).
using Q=System.Console;
// mod 8 table (the block of zeros is what we are after - it's everywhere we /can't/ go)
// 0 (space)
// O 0
// X 0
// S 3
// + 3
// E 5
struct P
{
int p,d;
static void Main()
{
// it's probably a bad thing that I have my own standards for naming this stupid read sequence by now
string D="", // map
L; // line/path char
int w=0, // width
W=0, // full length
o, // next state to expand
n=1; // next state to fill
for(;(L=Q.ReadLine())!=null;D+=L) // read in map
w=(o=(L+="X").Length+1)>w?o:w; // assertain max length (and mark end, and remove any need for wrap checking)
// now we need to add those trailing spaces...
for(;W<D.Length;)
D=D.Insert(W+1,"".PadLeft(D[W++]>87?w-W%w:0)); // inject a load of spaces if we hit an X
P[]K=new P[W*6]; // create space for due states (can't be more states than 6*number of cells)
var T=new string[W*6]; // create space for routes (never done it this way before, kind of exciting :D)
P c=K[o=0]=new P{p=D.IndexOf('S')}; // set first state (assignment to c is just to make the lambda shut up about unassigned variables)
// run bfs
for(
System.Action A=()=> // this adds c to the list of states to be expanded, if a whole load of checks pass
{
if(//n>0& // we havn't already finished - we don't need this, because we can't win on the first turn, so can't win unless we go forward, which we check last
c.p>=0&c.p<W& // c is within bounds
System.Array.IndexOf(K,c)<0&& // we havn't seen c yet (the && is to prevent the following lookup IOBing)
D[c.p]%8>0) // and we can move here (see table at top of code)
{
T[n]=T[o]+L; // store route
K[n]=c; // store state
n=D[c.p]==69?-n:n+1; // check if we are at the end, if so, set n to be negative of itself so we know, and can look up the route (otherwise, increment n)
}
}
;o<n;o++) // o<n also catches n<0
{
c=K[o]; // take current
L="R"; // say we are going right
c.d=++c.d%6; // turn right
A(); // go!
L="L"; // say we are going left
c.d=(c.d+4)%6; // turn left
A(); // go!
L="F"; // say we - you get the picture
c=K[o];
c.p+=new[]{~w,1-w,2,1+w,w-1,-2}[c.d%6]; // look up direction of travel (~w = -w-1)
A();
}
// check if we visited the end
Q.WriteLine(n>0?"Invalid maze!":T[-n]); // if n<0, then we found the end, so spit out the corresponding route, otherwise, the maze is invlida
}
}
Як і більшість моїх графічних пошуків на цьому сайті, я добре використовую структури C #, які за замовчуванням можна порівняти за буквальним значенням.