1つのソリューションのみでマルチレベルの5x5x5ラビリンスを作成する


11

この課題の目的は、以下を正常に実行する最短のコード(文字)を作成することです。

仕様

  • 5x5x5 labyrinthを正確に作成する必要があります1 possible solution(これ以上、それ以下)
  • ラビリンスを作成する必要があります randomly 何年も実行を続ける場合、既存のソリューションをすべて生成できる必要があります。
  • startfinishに配置する必要があります*opposite corners
  • マップoutputは次のいずれかの形式である必要があります。

オプションの出力形式1 strings, printed or alerted

xxxxx,xxxxx,xxxxx,xxxxx,xxxxx/
xxxxx,xxxxx,xxxxx,xxxxx,xxxxx/
xxxxx,xxxxx,xxxxx,xxxxx,xxxxx/
xxxxx,xxxxx,xxxxx,xxxxx,xxxxx/
xxxxx,xxxxx,xxxxx,xxxxx,xxxxx

オプションの出力形式2 arrays

[[xxxxx,xxxxx,xxxxx,xxxxx,xxxxx],
[xxxxx,xxxxx,xxxxx,xxxxx,xxxxx],
[xxxxx,xxxxx,xxxxx,xxxxx,xxxxx],
[xxxxx,xxxxx,xxxxx,xxxxx,xxxxx],
[xxxxx,xxxxx,xxxxx,xxxxx,xxxxx]]

出力ノート:

  • 使用0のためにempty1のためにsquares

  • ブレークラインがありませ必要

  • indexが何であるかを決定しますが、それをうまく説明するようにしてください


*ここに、私が反対の角を意味する例があります:

ここに画像の説明を入力してください

明確化

  • 入居できませんdiagonal
  • 同じパスで2回渡すことはできません
  • inaccessible areas許可されています
  • あなたはgo up/down連続して複数のレベルにすることができます

チップ:

  • それらを壁として見るのではなく5x5x5、それらのいくつかが欠落している正方形のスタックとしてそれらを見て、欠落しているものを通過することができます

不明な点がある場合は、私に尋ねてください:)
ajax333221

3
ただし、明確にしたい点が1つあります。壁正方形の間に配置されているのか、それとも壁正方形全体を埋めているのか。
イルマリカロネン

1
いくつかの場所で5x5(2D配列)と言いますが、コードサンプルと画像は5x5x5(3D配列)を示しています。3Dアレイは何を意味するのでしょうか?
ケイVerens

1
ソリューションが有効なラビリンスであるとどのように決定されますか?つまり、正しい道にある分枝の数ですか?それは1対0の比率と関係があるのでしょうか?
ケイVerens

2
「迷宮はランダムに作成する必要があります」と言うとき、どのような制限を推測する必要がありますか?たとえば、現在のルールの文字通りの読み取りのように、2つのハードコードされた出力をランダムに選択するプログラムを許可するつもりはないと思います。
ピーターテイラー

回答:


10

C ++ C、約1000 670 643 395 297 248文字

サンプル出力:

00111,10011,10111,00110,11000,
11001,01010,00100,11011,10101,
10111,10101,10001,01010,00101,
11001,11110,11100,11110,10101,
11100,10010,11001,10101,00000,

仕組み:プログラムは、Brownian Motionを使用してソリューションを生成します。開始点が設定されます。次に、ランダムなポイントが選択され、開始ブランチ上の1つだけのポイントに触れるまで、ランダムに繰り返し移動されます。次に、ポイントが設定され、エンドポイントにも触れると、プログラムが終了し、マトリックスが表示されます。2つのブランチを結合できるポイントはないため、ラビリンスを通るパスは1つだけです。プログラムはrand関数とコマンドライン整数引数をシードとして使用するため、十分なrand関数を使用すると、最終的にすべての有効なラビリンスを生成できるはずです(ただし、このアルゴリズムは非接続領域を作成しないため、すべてを生成しません可能な迷路)。

ブラウン運動は不要であることが判明したため削除され、削除によりコードが大幅に簡素化されました。しかし、それはより良い迷路を作ったと思います。同様に、128ビットのシードよりもステートレスな乱数ジェネレータを必要とする方が理にかなっているため、シードの引数は削除されました。

分岐に追加されたポイントが複数のパスを作成する可能性があるため、プログラムが無限ループに陥る可能性があります。これは修正可能ですが、コードゴルフの問題にならないほどまれだと思います。

#define M m[*p+1][p[1]][p[2]]
#define F(a,b)for(p[a]=5;p[a]--;putchar(b))
#define f for(i=3;i--;p[i]
p[]={4,4,4},h[3],m[7][6][6]={1};
main(i){
    for(M=2;h[1]^1||(M=1)^h[2];){
        f=rand()%5)
            h[i]=0;
        f++)
            p[i]++,
            h[M]++,
            p[i]-=2,
            h[M]++;
    }
    F(0,10)
        F(1,44)
            F(2,48+!M);
}

読みやすくするために、表示されるコードに改行とインデントを追加しました。


あなたはこれに勝つと思います;-)私はそこまで私を縮小する方法はありません
Kae Verens

私は本当に競争を楽しんだ:-)私たちがまだ唯一の答えであることに少し驚いています。
Sir_Lagsalot

どういうわけか、分岐点や決定ノードのない単純なパスは、真の迷路としての資格を持たないようです。ブラインドアレーを追加してみてください。
DavidC

@David Carraherこのアルゴリズムは、サンプルに示すように行き止まりと分岐パスを生成します。新しいポイントが既存の2つのブランチを接続することを許可しないと、迷路内の複数のソリューションまたはサイクルが防止されます。
Sir_Lagsalot

@Sir_Lagsalot説明をありがとう
-DavidC

5

JavaScript、874 816 788 686 682 668 637文字

サンプル出力:

00000,10111,10111,01010,11000
01011,01000,01010,01111,00011
00100,11010,00111,10111,11010
01111,10001,01110,01010,01000
00000,11110,00001,10101,10110

これは、ポイント[0,0,0]から開始し、許可される限り、0の隣にもう1つ0をランダムに追加します(allowed ==新しい0は、発信者を除く他の0の隣ではありません)。可能な追加。

新しい0が出口点の隣にある場合(x * y * z == 48)、出口を開きます。

ゴルフをした

b=[]
I=Math.random
for(i=5;i--;)for(j=5,b[i]=[];j--;)b[i][j]=[1,1,1,1,1]
b[0][0][0]=0
k=[[0,0,0]]
function q(x,y,z){J=b[x]
if(x<0||y<0||z<0||x>4||y>4||z>4||!J[y][z])return 
n=6-!x||b[x-1][y][z]
n-=!y||J[y-1][z]
n-=!z||J[y][z-1]
n-=x==4||b[x+1][y][z]
n-=y==4||J[y+1][z]
n-=z==4||J[y][z+1]
n==1&&v.push([x,y,z])}while(I){F=k.length
B=k[C=0|I(v=[])*F]
x=B[0]
q(x-1,y=B[1],z=B[2])
q(x,y-1,z)
q(x,y,z-1)
q(x+1,y,z)
q(x,y+1,z)
q(x,y,z+1)
if(D=v.length){k.push(A=v[0|I()*D])
b[A[0]][A[1]][A[2]]=0
if(A[0]*A[1]*A[2]==48)b[4][4][4]=I=0}else{for(E=[];F--;)F^C&&E.push(k[F])
k=E}}for(i=25;i--;)b[H=0|i/5][i%5]=b[H][i%5].join('')
alert(b.join("\n"))

元の

window.map=[];
for (i=0;i<5;++i) {
  map[i]=[];
  for (j=0;j<5;++j) {
    map[i][j]=[1,1,1,1,1];
  } 
} 
points=[[0,0,0]];
map[0][0][0]=0;
function spaces(x,y,z) {
  var n=6;
  if (x<0 || y<0 || z<0) return 0;
  if (x>4 || y>4 || z>4) return 0;
  if (!map[x][y][z]) return 0;
  if (!x || map[x-1][y][z]) n--;
  if (!y || map[x][y-1][z]) n--;
  if (!z || map[x][y][z-1]) n--;
  if (x==4 || map[x+1][y][z]) n--;
  if (y==4 || map[x][y+1][z]) n--;
  if (z==4 || map[x][y][z+1]) n--;
  return n;
} 
do {
  var index=Math.floor(Math.random()*points.length);
  point=points[index];
  v=[];
  x=point[0];
  y=point[1];
  z=point[2];
  spaces(x-1,y,z)==1 && v.push([x-1,y,z]);
  spaces(x,y-1,z)==1 && v.push([x,y-1,z]);
  spaces(x,y,z-1)==1 && v.push([x,y,z-1]);
  spaces(x+1,y,z)==1 && v.push([x+1,y,z]);
  spaces(x,y+1,z)==1 && v.push([x,y+1,z]);
  spaces(x,y,z+1)==1 && v.push([x,y,z+1]);
  if (v.length) {
    var point=v[Math.floor(Math.random()*v.length)];
    points.push(point);
    map[point[0]][point[1]][point[2]]=0;
    if (point[0]*point[1]*point[2]==48) {
      map[4][4][4]=0;
    } 
  } 
  else {
    var np=[];
    for (var i=0;i<points.length;++i) {
      i!=index && np.push(points[i]); 
    } 
    points=np;
  } 
} while(points.length);
for (i=0;i<5;++i) {
  for (j=0;j<5;++j) {
    map[i][j]=map[i][j].join('');
  } 
  map[i]=map[i].join();
} 
alert(map.join("\n"));

4

Mathematica:True Labyrinth(827文字)

もともと、{1,1,1}から{5,5,5}へのパスを作成しましたが、間違ったターンをする可能性がなかったため、分岐または「決定ポイント」(次数> 2)を導入しました。どちらに行くかを決める必要があります。結果は、真の迷路または迷路です。

「盲目の路地」は、単純で直接的な道を見つけるよりもはるかに解決が困難でした。最も困難なことは、パス内のサイクルを排除し、ソリューションパスからのサイクルを許可することでした。

次の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",...}}上記のソリューションに対応する迷路または迷路を示しています。

解決策1

これは5x5x5に挿入された同じ迷路ですGridGraph。番号付きの頂点は、ラビリンスからの最短経路上のノードです。34、64、および114の分岐点または決定点に注意してください。グラフはソリューションの一部ではありませんが、グラフのレンダリングに使用されるコードを含めます。

HighlightGraph[gg = GridGraph[ConstantArray[5, 3]], g,  
 GraphHighlightStyle ->"DehighlightFade", 
 VertexLabels -> Rule @@@ Transpose[{s, s}] ]

解決策2

そして、このグラフは迷宮の解決策のみを示しています。

HighlightGraph[gg = GridGraph[ConstantArray[5, 3]], 
   Join[s, e[s]], GraphHighlightStyle -> "DehighlightFade", VertexLabels -> Rule @@@    Transpose[{s, s}] ]

solution3

最後に、コードの読み取りに役立ついくつかの定義:

定義


元のソリューション(432文字、パスを生成しましたが、真の迷路や迷路ではありません)

個別のユニットキューブで構成される5x5x5の大きなソリッドキューブを想像してください。以下は、{1,1,1}および{5,5,5}のユニットキューブなしで始まります。これらはソリューションの一部でなければならないことがわかっているからです。次に、{1,1,1}から{5,5,5}への障害のないパスができるまで、ランダムキューブを削除します。

「labyrinth」は、削除されたユニットキューブが与えられた場合の最短経路です(複数可能な場合)。

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"}}

技術的には、間違った方向転換はできないため、これはまだ真の迷路ではありません。しかし、グラフ理論に依存しているので、出発点としてそれが面白いと思いました。

このルーチンは実際に迷路を作りますが、サイクルを引き起こす可能性のある空の場所をすべて塞ぎました。サイクルを削除する方法を見つけたら、ここにそのコードを含めます。


素敵な更新、更新されたソリューションは、ソリューション以外のパスでのサイクルを許可するので、迷惑な迷路になります。
Sir_Lagsalot

ありがとう。解決策のパス自体を、最終ノードから随時遠ざかるようにしたいと考えています。現在、これは推奨されていません(完全に防止されてFindShortestPathいるわけではありません)。
DavidC

私はMatlabにあまり詳しくありませんが、FindShortestPathのようなことをして、最短パスの各ノードにバイアスを追加し、バイアスを考慮してFindShortestPathを再度実行して、最短ソリューションのノードを回避できますか?これも繰り返し行うことができます。どのような種類のパスが生成されるかを知りたいと思います。
Sir_Lagsalot

@Sir_Lagsalot私は(ここではMathematicaのSEグループのための質問として投稿mathematica.stackexchange.com/questions/4084/...
DavidC
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.