Mathematica: Wahres Labyrinth (827 Zeichen)
Ursprünglich habe ich einen Pfad von {1,1,1} nach {5,5,5} erstellt, aber da keine möglichen falschen Abbiegungen möglich waren, habe ich Gabeln oder "Entscheidungspunkte" (Eckpunkte> 2) eingeführt, bei denen man müsste sich entscheiden, welchen Weg man gehen soll. Das Ergebnis ist ein echtes Labyrinth oder Labyrinth.
Die "Sackgassen" waren weitaus schwieriger zu lösen als einen einfachen, direkten Weg zu finden. Die größte Herausforderung bestand darin, Zyklen innerhalb des Pfads zu eliminieren und gleichzeitig Zyklen außerhalb des Lösungspfads zuzulassen.
Die folgenden zwei Codezeilen werden nur zum Rendern der gezeichneten Diagramme verwendet, sodass der Code nicht zählt, da er in der Lösung nicht verwendet wird.
o = Sequence[VertexLabels -> "Name", ImagePadding -> 10, GraphHighlightStyle -> "Thick",
ImageSize -> 600];
o2 = Sequence[ImagePadding -> 10, GraphHighlightStyle -> "Thick", ImageSize -> 600];
Verwendeter Code:
e[c_] := Cases[EdgeList[GridGraph[ConstantArray[5, 3]]], j_ \[UndirectedEdge] k_ /; (MemberQ[c, j] && MemberQ[c, k])]
m[] :=
Module[{d = 5, v = {1, 125}},
While[\[Not] MatchQ[FindShortestPath[Graph[e[v]], 1, 125], {1, __, 125}],
v = Join[v, RandomSample[Complement[Range[125], v], 1]]];
Graph[e[Select[ConnectedComponents[Graph[e[v]]], MemberQ[#, 1] &][[1]]]]]
w[gr_, p_] := EdgeDelete[gr, EdgeList[PathGraph[p]]]
y[p_, u_] := Select[Intersection[#, p] & /@ ConnectedComponents[u], Length[#] > 1 &]
g = HighlightGraph[lab = m[], PathGraph[s = FindShortestPath[lab, 1, 125]],o]
u = w[g, s]
q = y[s, u]
While[y[s, u] != {}, u = EdgeDelete[u, Take[FindShortestPath[u, q[[1, r = RandomInteger[Length@q[[1]] - 2] + 1]],
q[[1, r + 1]]], 2] /. {{a_, b_} :> a \[UndirectedEdge] b}];
q = y[s, u]]
g = EdgeAdd[u, EdgeList@PathGraph[s]];
Partition[StringJoin /@ Partition[ReplacePart[Table["x", {125}],
Transpose[{VertexList[g], Table["o", {Length[VertexList@g]}]}]/. {{a_, b_} :> a -> b}], {5}], 5]
Beispielausgabe
{{"oxooo", "xxooo", "xoxxo", "xoxxo", "xxoox"}, {"ooxoo", "xoooo", "ooxox", "oooxx", "xooxx"}, {"oooxx", "ooxxo", "ooxox", "xoxoo", "xxxoo"}, {"oxxxx", "oooox", "xooox", "xoxxx", "oooxx"}, {"xxxxx", "ooxox", "oooox" "," xoxoo "," oooxo "}}
Unter der Haube
Das Bild unten zeigt das Labyrinth oder Labyrinth, das der ({{"ooxoo",...}}
oben gezeigten Lösung entspricht :
Hier ist das gleiche Labyrinth in einem 5x5x5 eingefügt GridGraph
. Die nummerierten Eckpunkte sind Knoten auf dem kürzesten Weg aus dem Labyrinth. Beachten Sie die Gabeln oder Entscheidungspunkte bei 34, 64 und 114. Ich werde den Code einfügen, der zum Rendern des Diagramms verwendet wird, obwohl er nicht Teil der Lösung ist:
HighlightGraph[gg = GridGraph[ConstantArray[5, 3]], g,
GraphHighlightStyle ->"DehighlightFade",
VertexLabels -> Rule @@@ Transpose[{s, s}] ]
Und diese Grafik zeigt nur die Lösung für das Labyrinth:
HighlightGraph[gg = GridGraph[ConstantArray[5, 3]],
Join[s, e[s]], GraphHighlightStyle -> "DehighlightFade", VertexLabels -> Rule @@@ Transpose[{s, s}] ]
Schließlich einige Definitionen, die beim Lesen des Codes hilfreich sein können:
Ursprüngliche Lösung (432 Zeichen, Produziert einen Pfad, aber kein echtes Labyrinth oder Labyrinth)
Stellen Sie sich einen 5x5x5 großen festen Würfel vor, der aus verschiedenen Einheitswürfeln besteht. Das Folgende beginnt ohne Einheitswürfel bei {1,1,1} und {5,5,5}, da wir wissen, dass sie Teil der Lösung sein müssen. Dann werden zufällige Würfel entfernt, bis ein ungehinderter Pfad von {1,1,1} zu {5,5,5} vorhanden ist.
Das "Labyrinth" ist der kürzeste Weg (wenn mehr als einer möglich ist) angesichts der entfernten Einheitswürfel.
d=5
v={1,d^3}
edges[g_,c_]:=Cases[g,j_\[UndirectedEdge] k_/;(MemberQ[c,j]&&MemberQ[c,k])]
g:=Graph[v,edges[EdgeList[GridGraph[ConstantArray[d,d]]],v]];
While[\[Not]FindShortestPath[g,1,d^3]!={},
v=Join[v,RandomSample[Complement[Range[d^3],v],1]]]
Partition[Partition[ReplacePart[
Table["x",{d^3}],Transpose[{FindShortestPath[g,1,d^3],Table["o",{Length[s]}]}]
/.{{a_,b_}:> a->b}],{d}]/.{a_,b_,c_,d_,e_}:> StringJoin[a,b,c,d,e],5]
Beispiel:
{{"ooxxx", "xxxxx", "xxxxx", "xxxxx", "xxxxx"},
{"xoxxx", "xoooo", "xxxxo", "xxxxo", "xxxxo"},
{"xxxxx", "xxxxx", "xxxxx", "xxxxx", "xxxxo"},
{"xxxxx", "xxxxx", "xxxxx", "xxxxx", "xxxxo"},
{"xxxxx", "xxxxx", "xxxxx", "xxxxx", "xxxxo"}}
Technisch gesehen ist dies noch kein echtes Labyrinth, da es keine falschen Wendungen gibt, die man machen kann. Aber ich fand es zunächst interessant, da es auf der Graphentheorie beruht.
Die Routine bildet tatsächlich ein Labyrinth, aber ich habe alle leeren Stellen verstopft, die zu Zyklen führen könnten. Wenn ich einen Weg finde, Zyklen zu entfernen, werde ich diesen Code hier einfügen.