Mathematica: настоящий лабиринт (827 символов)
Первоначально я создал путь от {1,1,1} до {5,5,5}, но поскольку не было возможных неправильных поворотов, я ввел вилки или «точки принятия решения» (вершины степени> 2), где нужно было бы решить, в какую сторону идти. В результате получается настоящий лабиринт или лабиринт.
«Слепые переулки» решить гораздо сложнее, чем найти простой прямой путь. Самым сложным было устранить циклы на пути, позволяя циклам отклоняться от пути решения.
Следующие две строки кода используются только для визуализации нарисованных графиков, поэтому код не учитывается, так как он не используется в решении.
o = Sequence[VertexLabels -> "Name", ImagePadding -> 10, GraphHighlightStyle -> "Thick",
ImageSize -> 600];
o2 = Sequence[ImagePadding -> 10, GraphHighlightStyle -> "Thick", ImageSize -> 600];
Используемый код:
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]
Образец вывода
{{"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 "}}
Под капотом
На рисунке ниже показан лабиринт или лабиринт, который соответствует решению, ({{"ooxoo",...}}
показанному выше:
Вот тот самый лабиринт, вставленный в 5х5х5 GridGraph
. Нумерованные вершины - это узлы на кратчайшем пути из лабиринта. Обратите внимание на разветвления или точки принятия решений на 34, 64 и 114. Я включу код, используемый для визуализации графика, даже если он не является частью решения:
HighlightGraph[gg = GridGraph[ConstantArray[5, 3]], g,
GraphHighlightStyle ->"DehighlightFade",
VertexLabels -> Rule @@@ Transpose[{s, s}] ]
И этот график показывает только решение лабиринта:
HighlightGraph[gg = GridGraph[ConstantArray[5, 3]],
Join[s, e[s]], GraphHighlightStyle -> "DehighlightFade", VertexLabels -> Rule @@@ Transpose[{s, s}] ]
Наконец, некоторые определения, которые могут помочь при чтении кода:
Оригинальное решение (432 знака, Произведен путь, но не настоящий лабиринт или лабиринт)
Представьте себе большой твердый куб 5x5x5, состоящий из отдельных единичных кубов. Следующее начинается без единичных кубов в {1,1,1} и {5,5,5}, так как мы знаем, что они должны быть частью решения. Затем он удаляет случайные кубы, пока не появится беспрепятственный путь от {1,1,1} до {5,5,5}.
«Лабиринт» - это кратчайший путь (если возможно более одного) из кубов, которые были удалены.
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]
Пример:
{{"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"}}
Технически это еще не настоящий лабиринт, поскольку нет неправильных поворотов, которые можно совершить. Но я подумал, что это интересно с самого начала, поскольку он опирается на теорию графов.
Рутина на самом деле делает лабиринт, но я заткнул все пустые места, которые могли вызвать циклы. Если я найду способ удалить циклы, я включу этот код здесь.