단 하나의 솔루션으로 멀티 레벨 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
  • 동일한 경로에서 두 번 통과 할 수 없습니다
  • 갖는 inaccessible areas것은 허용된다
  • go up/down연속으로 여러 레벨을 할 수 있습니다

팁 :

  • 그것들을 벽으로 보지 말고 대신 5x5x5에 사각형 의 더미 로 보아라.

불분명 한 것이 있으면 나에게 물어보십시오 :)
ajax333221

3
그러나 벽 정사각형 사이에 배치 합니까, 아니면 벽이 전체 정사각형을 채우나요?
Ilmari Karonen

1
몇 군데에서는 5x5 (2D 배열)라고 말하지만 코드 샘플과 이미지는 5x5x5 (3D 배열)를 나타냅니다. 3D 배열이 무엇을 의미한다고 생각합니까?
Kae Verens

1
솔루션이 유효한 미로라고 어떻게 결정됩니까? 내 말은, 올바른 경로가 가지고있는 파생 품의 수입니까? 1 대 0의 비율과 관련이 있습니까?
Kae Verens

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 을 사용하여 솔루션을 생성합니다. 시작점이 설정됩니다. 그런 다음 임의 지점이 선택 되고 시작 분기의 한 지점에만 닿을 때까지 무작위로 반복적으로 이동 합니다. 그런 다음 점이 설정되고 끝점에 닿으면 프로그램이 종료되고 매트릭스가 표시됩니다. 지점이 두 가지로 연결될 수 없으므로 미로를 통과하는 경로는 하나뿐입니다. 프로그램은 rand 함수 와 명령 행 정수 인수를 시드로 사용합니다. 하므로 충분한 rand 함수를 사용하면 모든 유효한 미로를 생성 할 수 있습니다 (이 알고리즘은 연결되지 않은 영역을 만들지 않으므로 모든 것을 생성하지는 않습니다) 가능한 미로).

Brownian 모션은 불필요한 것으로 판명되어 삭제되었으며 코드를 크게 단순화합니다. 나는 그것이 더 좋은 미로를 만들었다 고 생각합니다. 마찬가지로 시드 인수는 삭제되었습니다. 상태 비 저장 난수 생성기를 요구하면 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이 알고리즘은 샘플에 표시된대로 데드 엔드 및 분기 경로를 생성합니다. 새로운 지점이 이미 존재하는 두 개의 분기를 연결하도록 허용하지 않으면 단순히 미로에서 여러 솔루션 또는주기를 방지 할 수 있습니다.
Sir_Lagsalot

@Sir_Lagsalot 설명해 주셔서 감사합니다
DavidC

5

자바 스크립트, 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 옆에 하나 이상의 0을 추가하여 임의로 추가하여 작동합니다 (허용 == 새로운 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

매스 매 티카 : 진정한 미로 (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",...}}위에 표시된 솔루션에 해당하는 미로 또는 미로를 보여줍니다 .

해결책 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}] ]

해결책 3

마지막으로 코드를 읽는 데 도움이되는 몇 가지 정의가 있습니다.

정의


독창적 인 솔루션 (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"}}

기술적으로 이것은 아직 진정한 미로가 아닙니다. 왜냐하면 사람이 할 수있는 잘못된 회전이 없기 때문입니다. 그러나 그래프 이론에 의존하기 때문에 시작으로 재미 있다고 생각했습니다.

루틴은 실제로 미로를 만들지 만 사이클을 일으킬 수있는 모든 빈 위치를 꽂았습니다. 사이클을 제거하는 방법을 찾으면 여기에 해당 코드를 포함시킵니다.


좋은 업데이트, 나는 당신의 업데이트 된 솔루션이 비 솔루션 경로에서 사이클을 허용하여 더 혼란스러운 미로를 만듭니다.
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.