สร้างเขาวงกต 5x5x5 หลายระดับด้วยโซลูชันเดียวเท่านั้น


11

เป้าหมายของความท้าทายนี้คือการสร้างรหัสที่สั้นที่สุด (เป็นตัวอักษร) ที่ทำสิ่งต่อไปนี้สำเร็จ:

ข้อมูลจำเพาะ :

  • ต้องสร้าง5x5x5 labyrinthด้วยอย่างแน่นอน1 possible solution(ไม่มากไม่น้อยกว่า)
  • ต้องสร้างเขาวงกต randomly มันจะต้องสามารถสร้างโซลูชันที่มีอยู่ได้ทั้งหมดหากปล่อยทิ้งไว้เป็นเวลาหลายปี
  • startและfinishจะต้องอยู่ใน*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สำหรับemptyและ1สำหรับsquares

  • ไม่จำเป็นต้องขึ้นบรรทัดใหม่

  • คุณเป็นคนตัดสินใจว่าอะไรindexคืออะไร แต่ขอให้แน่ใจว่าได้อธิบายให้ดี


* นี่คือตัวอย่างของสิ่งที่ฉันหมายถึงโดยมุมตรงข้าม:

ป้อนคำอธิบายรูปภาพที่นี่

ชี้แจง :

  • ไม่สามารถย้ายเข้าdiagonal
  • ไม่สามารถผ่านสองครั้งบนเส้นทางเดียวกัน
  • ต้องinaccessible areasได้รับอนุญาต
  • คุณสามารถgo up/downมากกว่าหนึ่งระดับในแถว

เคล็ดลับ:

  • อย่ามองมันเป็นกำแพงแทนที่จะมองมันเป็น5x5x5กองสี่เหลี่ยมที่บางส่วนหายไปและคุณสามารถผ่านสิ่งที่ขาดหายไปได้

หากสิ่งที่ไม่ชัดเจนเพียงแค่ถามฉัน :)
ajax333221

3
อย่างไรก็ตามมีรายละเอียดหนึ่งที่ฉันต้องการชี้แจง: มีผนังวางอยู่ระหว่างช่องสี่เหลี่ยมหรือผนังเต็มทั้งสี่เหลี่ยมหรือไม่
Ilmari Karonen

1
คุณพูดได้ว่า 5x5 (อาเรย์ 2 มิติ) ในบางแห่ง แต่ตัวอย่างรหัสและรูปภาพแนะนำ 5x5x5 (อาเรย์ 3 มิติ) ฉันคิดว่าอาเรย์สามมิตินั้นมีความหมายอะไร?
Kae Verens

1
เป็นวิธีการตัดสินใจว่าวิธีการแก้ปัญหาเป็นเขาวงกตที่ถูกต้อง? ฉันหมายความว่ามันเป็นจำนวนหน่อที่เส้นทางที่ถูกต้องหรือไม่? มันเกี่ยวกับอัตราส่วน 1s ถึง 0s ไหม
Kae Verens

2
เมื่อคุณพูดว่า "เขาวงกตต้องถูกสร้างขึ้นแบบสุ่ม" เราควรสรุปข้อ จำกัด อะไรบ้าง ตัวอย่างเช่นฉันเข้าใจว่าคุณไม่ต้องการให้อนุญาตตามที่อ่านกฎของตัวอักษรในปัจจุบันโปรแกรมที่เลือกระหว่างสองฮาร์ดโค้ดเอาท์พุทแบบสุ่ม
Peter Taylor

คำตอบ:


10

C ++ C ประมาณ 1,000 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เพื่อสร้างโซลูชัน ตั้งจุดเริ่มต้น จากนั้นจะมีการเลือกจุดสุ่มและย้ายแบบสุ่มซ้ำ ๆจนกว่าจะสัมผัสจุดหนึ่งและจุดเดียวในจุดเริ่มต้น จากนั้นจุดจะถูกตั้งค่าและหากสัมผัสจุดสิ้นสุดโปรแกรมจะออกและเมทริกซ์จะปรากฏขึ้น เนื่องจากไม่มีจุดที่สามารถเข้าร่วมสองสาขาได้จึงมีเพียงเส้นทางเดียวผ่านเขาวงกต โปรแกรมใช้ฟังก์ชั่นแรนด์และอาร์กิวเมนต์จำนวนเต็มบรรทัดคำสั่งเป็นเมล็ดดังนั้นด้วยฟังก์ชั่นแรนด์ที่เพียงพอมันควรจะเป็นไปได้ที่จะสร้างเขาวงกตที่ถูกต้องในที่สุด (อัลกอริทึมนี้จะไม่สร้างพื้นที่ที่ไม่เชื่อมต่อกัน) เขาวงกตที่เป็นไปได้ )

การเคลื่อนไหวของบราวน์ลดลงเนื่องจากปรากฏว่าไม่จำเป็นและการลบจะทำให้รหัสง่ายขึ้นอย่างมาก ฉันคิดว่ามันทำให้เขาวงกตดีกว่า ในทำนองเดียวกันการโต้แย้งของเมล็ดก็ลดลงเนื่องจากต้องใช้ตัวสร้างตัวเลขสุ่มไร้สัญชาติทำให้ฉันมีความหมายมากกว่าเมล็ด 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

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 ตัวถัดจาก 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

Mathematica: True Labyrinth (827 ตัวอักษร)

เดิมทีฉันสร้างเส้นทางจาก {1,1,1} ถึง {5,5,5} แต่เนื่องจากไม่มีการทำผิดที่เป็นไปได้ฉันจึงแนะนำส้อมหรือ "จุดตัดสินใจ" (vertices of degree> 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", "oooxx", "oooxx", "xooxx", "ooxxo", "ooxox", "xoxoo", "xxxoo"}, {"oxxxx", "oooox", "xooox", "xoxox", "oooxx"}, {"xxxxx", "ooxox", "oooox" "," xoxoo "," oooxo "}}

ภายใต้ประทุน

ภาพด้านล่างแสดงเขาวงกตหรือเขาวงกตที่สอดคล้องกับวิธีแก้ปัญหาที่({{"ooxoo",...}}แสดงด้านบน:

solution1

นี่คือเขาวงกตเดียวกันแทรกอยู่ใน GridGraph5x5x5 จุดยอดที่มีหมายเลขคือโหนดบนเส้นทางที่สั้นที่สุดออกจากเขาวงกต สังเกตส้อมหรือจุดตัดสินใจที่ 34, 64 และ 114 ฉันจะรวมรหัสที่ใช้ในการเรนเดอร์กราฟแม้ว่ามันจะไม่ได้เป็นส่วนหนึ่งของโซลูชัน:

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

solution2

และกราฟนี้แสดงวิธีแก้ปัญหาให้กับเขาวงกตเท่านั้น:

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}

"เขาวงกต" เป็นเส้นทางที่สั้นที่สุด (ถ้ามีมากกว่าหนึ่งที่เป็นไปได้) ที่กำหนดให้หน่วยลูกบาศก์ที่ถูกลบออก

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.