C #, 600 574 Bytes
Vollständiges Programm, akzeptiert Eingaben von STDIN und gibt sie an STDOUT aus.
Bearbeiten: Es gab einen Fehler in der Wrap-Behandlung (bei keinem der angegebenen Testfälle ist ein Fehler aufgetreten), der 1 Byte hinzugefügt hätte, sodass ich etwas mehr Golf gespielt habe, um dies zu kompensieren.
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]);}}
Zunächst wird die Karte eingelesen und (
an jede Zeile angehängt , damit sie weiß, wo sie endet. Anschließend können Sie eine Menge Leerzeichen hinzufügen, um die Karte rechteckig zu machen Wir führen Wickelprüfungen durch (siehe unten). Es berechnet die Breite des Rechtecks an einem bestimmten Punkt und ermittelt die Gesamtlänge der Karte.
Als nächstes wird alles für eine Breitensuche initialisiert. Es werden zwei große Arrays erstellt, eines zum Speichern aller Zustände, die wir bei unserer Suche erforschen müssen, das andere zum Aufzeichnen der Route, die wir genommen haben, um zu jedem Zustand zu gelangen. Der Anfangszustand wird zum fälligen Array hinzugefügt, wobei der Kopf- und der Endzeiger oben voreingestellt sind. Alles ist 1-indiziert.
Wir iterieren dann, bis der Schwanz gegen den Kopf stößt, oder zumindest scheint er gegen den Kopf gestoßen zu sein. Für jeden Status, den wir besucht haben, versuchen wir, einen neuen Status an derselben Position hinzuzufügen, an der wir nach links oder rechts gedreht wurden, und dann einen, an der wir vorwärts gegangen sind. Die Richtungen sind indiziert, wobei die anfängliche Richtung (standardmäßig auf 0
) "oben links" entspricht.
Wenn wir versuchen, einen Zustand in die Warteschlange zu stellen, wird er gebunden, aber nicht umbrochen, da auf der rechten Seite Spalten mit Leerzeichen angezeigt werden, auf denen die Meldung "Dürfen wir hier sein?" check (du darfst nicht auf Leerzeichen sein). Wenn sich der Status in der Warteschlange befindet, prüfen wir, ob er sich in der E
Zelle befindet. Wenn dies der Fall ist, setzen wir den Kopf der Warteschlange auf minus, wodurch die Hauptschleife beendet und die letzte Zeile des Programms zum Drucken angewiesen wird Geben Sie die entsprechende Route und nicht die Fehlermeldung aus (die anzeigt, ob die zu erweiternden Zustände abgelaufen sind (der Schwanz stürzt gegen den Kopf).
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
}
}
Wie die meisten meiner Graph-Suchen auf dieser Site verwende ich C # -Strukturen, die standardmäßig anhand von Literalwerten verglichen werden.