Kiến trúc sư nhà tù, phiên bản ASCII


42

Dưới đây là sơ đồ của một nhà tù sử dụng các ký tự ASCII:

+------------------------------+
|                              |
|   X               X          |
|                              |
|                              D
D                              |
|                              |
|                              |
|        X           X   X     |
|                              |
+------------------------------+

Tường được làm từ các ký tự ống |, dấu gạch ngang -và cột +cho các góc và giao điểm. Ngoài ra còn có hai cửa được đánh dấu D(sẽ luôn ở bên trái và bên phải). Nhà tù chứa đầy những người đáng sợ được đánh dấu X.

Mục tiêu là xây dựng các bức tường để đáp ứng những điều sau đây:

  1. Mỗi người bị biệt giam;
  2. Có một hành lang chạy giữa hai cánh cửa;
  3. Mỗi ô chứa chính xác một cửa, được kết nối trực tiếp với hành lang chính;
  4. Tất cả không gian trong nhà tù được sử dụng bởi các phòng giam và hành lang;
  5. Mỗi ô chứa một người (nghĩa là không có ô trống).

Hành lang là một lối đi duy nhất, không rẽ nhánh và luôn rộng một ký tự. Đây là một giải pháp cho nhà tù ở trên:

+---------+--------------------+
|         |                    |
|   X     |         X          |
|         |           +--------+
+------D--+-----D-----+        D
D                       +---D--+
+----D--------+---D-----+      |
|             |         |      |
|        X    |      X  |X     |
|             |         |      |
+-------------+---------+------+

Bạn có thể cho rằng bất kỳ nhà tù đầu vào nào sẽ luôn có đầu ra hợp lệ. Dưới đây là một số nhà tù đầu vào, cùng với các đầu ra có thể:

+------------------------------+
|X X X X X X X X X X X X X X X |
|                              |
D                              D
|                              |
|              X               |
+------------------------------+

+-+-+-+-+-+-+-+-+-+-+-+-+-+-+--+
|X|X|X|X|X|X|X|X|X|X|X|X|X|X|X |
+D+D+D+D+D+D+D+D+D+D+D+D+D+D+D-+
D                              D
+----------------------D-------+
|              X               |
+------------------------------+

+-----------+
|X          |
|           |
|           |
|X         X|
|           |
|          X|
|           |
D           D
+-----------+

+-+-------+-+
|X|       D |
| D +---+ | |
+-+ |     | |
|X| | +---+X|
| | | |   +-+
| D | |    X|
+-+ | +-D---+
D   |       D
+---+-------+

+----------------+
|X    X    X    X|
|                |
D                |
|                |
|X    X    X     |
|                |
|                |
|                |
|     X    X     D
|                |
|                |
+----------------+

+---+---+----+---+
|X  | X |  X |  X|
+--D+--D+---D+--D+
D                |
+---+---+------+ |
|X  | X |  X   | |
+--D+--D+---D--+ |
|                |
| +-----+------+-+
| |   X |  X   | D
| +----D+---D--+ |
|                |
+----------------+

4
Giải pháp có thể: con đường phòng đầu tiên tiếp theo
Matthew Roh

Liên quan , có thể hữu ích khi xây dựng các bức tường.
TheLethalCoder

1
Điều gì ngăn cản tôi đặt các bức tường và một cánh cửa trực tiếp xung quanh mỗi tù nhân (như trong ví dụ thứ hai của bạn) và tuyên bố phần còn lại của không gian là một hành lang?
Fels

Xin lỗi, tìm thấy nó: "một ký tự rộng".
Fels

Câu trả lời:


15

Python 2 , 2986 2881 2949 2135 2075 2071 1996 byte

  • Đã lưu 105 byte, thực hiện chương trình như một hàm để tuân thủ các quy tắc chuẩn. Đã thực hiện đề xuất tab và hướng dẫn không gian của Wheat Wizard.
  • Đã thêm 68 byte do sửa lỗi.
  • Đã lưu 814 + 51 byte nhờ Halvard Hummel.
  • Đã lưu 9 + 4 byte.
  • Đã lưu 4 byte nhờ Erik the Outgolfer.
  • Đã lưu 71 byte nhờ đề xuất của ppperry.
exec r"""def Z(P):
 H,n,I,o,O,i,d,D,W=[type,range]+list(" dD#xX*");R=(1,0),(-1,0),(0,1),(0,-1)
 def F(j,k,l):P[j][k]=l
 def E(j,k,v,w):
	if G(j,k,v):F(k,j,w)
 def q(b,c,d):[[E(j+J,k+K,b,c)for J,K in M]&L if G(j,k,d)]
 def A(e,r,l,o,q):
	S,E,P[q][o],Q,X=P[q][o],e,0,[(o,q)],0
	for a,b in Q:
	 &R:
		x,y=a+j,b+k
		if(0<=x<w!=0<=y<h)<1:continue
		if e in((x,y),P[y][x]):X=1;e=x,y;break
		if I!=P[y][x]:continue
		F(y,x,P[b][a]+1);Q+=[(x,y)]
	 if X:break
	p,i=e,0
	while(o,q)!=p:
	 a,b=p;P[b][a],m=[r,l][l and i==1],0
	 &R:
		x,y=a+j,b+k
		if(0<=x<w!=0<=y<h)-1:continue
		if(H(P[y][x])==H(0))*(m==0 or P[y][x]<P[m[1]][m[0]]):m=x,y
	 p=m;i+=1
	P[q][o],P[e[1]][e[0]]=S,E;[F(k,j,I)&L if H(P[k][j])==H(0)]
 def B(N):
	[[E(j,k,"x*",I),0<j<w-1 and E(j,k,O,I)]&L]
	&L:
	 if G(j,k,D):[E(j+J,k+K,I,d)for J,K in M]
	 if G(j,k,O)and j==0:T=0,k
	if N:A(O,o,0,*T)
	U,V=M[-1];[[[F(k+K,j+J,I)for J,K in M if(P[k+K][j+J]!=i)*((0<=j+J+U<w!=0<=k+K+V<h and G(j+J+U,k+K+V,D))<1)],F(k,j,W),A(o,W,O,j,k),q(I,d,W),F(k,j,D)]&L if G(j,k,D)];q("xX*# @+-|",i,o)
 for j in"|+-":P=P.replace(j,i)
 P=list(map(list,P.split("\n")));h=len(P);w=len(P[0]);b,L,M,G="#+-|D",[(k,j)for k in n(w)for j in n(h)],[(k-1,j-1)for k in n(3)for j in n(3)if(j,k)!=(1,1)],lambda j,k,v:P[k][j]in v
 B(1);Y=lambda:0<j<w-1!=0<k<h-1and G(j,k,i);[[[F(k,j,o),F(k+g,j+N,i)]for N,g in((-1,-1),(-1,1),(1,-1),(1,1))if P[k][j+g]+P[k][j-g]==P[k+N][j+g]+P[k-N][j]==P[k+N][j]+i==o+i]&L if(j in(1,w-2)or k in(1,h-2))*Y()for N in n(w*h)];[F(k,j,I)&L if Y()];B(0)
 def c(x,y,b,l,d,f,Q):
	F(y,x,b)
	for J,K in M:Q+=[[],[(x+J,y+K)]][G(x+J,y+K,l)];E(x+J,y+K,d,f)
 &L:
	if G(j,k,D):Q=[(j,k)];[c(x,y,"@",W,d,I,Q)for x,y in Q if G(x,y,"X*")];[G(u,v,"X*")and[E(u+U,v+V,I,d)for U,V in M]or E(u,v,"@",I)for u,v in L];Q=Q[:1];[c(x,y,"$",I,"x*",i,Q)for x,y in Q];F(k,j,D)
 &L:E(j,k,"@$d",I);X=(k>0and G(j,k-1,b))+(k<h-1and G(j,k+1,b))-(j>0and G(j-1,k,b))-(j<w-1and G(j+1,k,b));E(j,k,i,{2:"+",X:"|",-X:"-"}[2])
 print"\n".join("".join(p)for p in P)""".replace("&","for j,k in ")

Hãy thử trực tuyến!

Nó đã được đánh xuống đáng kể; nhưng vẫn có thể có chỗ để cải thiện. Đoạn mã này, tuy nhiên, giải quyết tất cả các trường hợp thử nghiệm. Không chạy rất hiệu quả; đối với các nhà tù lớn, kiến ​​trúc sư có thể dành thời gian để tìm ra nó.
Sử dụng một thuật toán tìm đường đơn giản để kết nối cả hai cánh cửa và tù nhân với hành lang. Sau đó, nó gói gọn tất cả các tù nhân và các bức tường của họ và đẩy các bức tường nói trong không gian trống rỗng cho đến khi tất cả được lấp đầy. Bước cuối cùng, sự xuất hiện của nghệ thuật ASCII được thực hiện.

Mất tôi chắc chắn vài giờ để viết. Tôi hy vọng nó cũng hoạt động trên các nhà tù khác ngoài các trường hợp thử nghiệm. (Bạn không thể kiểm tra tất cả, phải không?)


Đối với nhiều cấp độ thụt đầu dòng, bạn có thể thay thế các khoảng trắng và tab. (dấu cách = 1 thụt lề, tab = 2 thụt lề)
Thuật sĩ lúa mì

1
Ngoài ra đây là một đoạn. Có nghĩa là bạn lấy đầu vào từ một biến khởi tạo trước ( P). Đây không phải là một định dạng IO được phép. Bạn nên sử dụng input()hoặc xác định một chức năng.
Thuật sĩ lúa mì

Vì đây là một đoạn mã lớn như vậy, nên cũng có khoảng một trăm thứ nhỏ hơn mà tôi thấy có thể chơi được. Tôi sẽ không liệt kê tất cả chúng bây giờ. Nhưng nếu bạn muốn tôi giúp bạn vượt qua họ, bạn có thể ping tôi trong trò chuyện. Vì bạn là một người dùng tương đối mới, tôi không biết bạn đã quen với việc chơi golf python như thế nào. Có lẽ bạn vẫn đang làm việc trên sân golf này một mình. :)
Thuật sĩ lúa mì

Đây là một cách phiên bản ngắn hơn thực hiện một số thủ thuật tôi đã thấy. Đó không phải là cách xa nhất mà nó có thể được đánh xuống, tôi thậm chí không biết thuật toán của bạn. Nhưng nó ngắn hơn khoảng 300 byte. Nó vẫn là một đoạn trích, vì vậy bạn sẽ cần phải làm cho nó tuân thủ.
Thuật sĩ lúa mì

1
@HalvardHummel Mục tiêu đã đạt được; chúng tôi dưới 2000 byte!
Jonathan Frech

4

C, 3732 3642 byte

Tôi chắc chắn có thể chơi golf này xa hơn một chút, nhưng đó là một khởi đầu khá tốt đẹp. Ban đầu tôi không biết rằng cách tiếp cận của tôi có một cái tên nên hét to với @TehPers vì đã cho tôi một cái tên để nghiên cứu. Tôi chắc chắn rất thích những thách thức mà câu hỏi này đưa ra. :)

-63 byte từ đề xuất của @ Jonathan. Tôi cũng thay thế charvới typedef char Rvà thay thế tất cả các literals nhân vật nhỏ hơn 100 với giá trị ASCII của họ với tổng số 90 byte

Một lời giải thích nhanh về mã của tôi.

  1. Chuyển mảng char thành mảng số nguyên lý tưởng (0 là khoảng trắng, 1 là tường, v.v.)
  2. Tạo sơ đồ Voronoi bằng cách sử dụng mọi người làm điểm
  3. Sử dụng các giao điểm (số 5 được bao quanh bởi ít nhất ba 5s khác) làm điểm xoay vòng cho đường dẫn
  4. Tạo hành lang bằng thuật toán tìm đường dẫn thiên lệch (nếu đi theo một chiều, hãy ưu tiên các đường dẫn không thay đổi hướng). Nó cũng sửa đổi lưới để nó thích đi bên cạnh một hành lang đã được thực hiện.
  5. Tái tạo sơ đồ để đặt các bức tường cuối cùng. Đảm bảo rằng tất cả không gian được sử dụng.
  6. Chuyển đổi bản đồ trở lại bản trình bày và in ASCII được định dạng chính xác.

Để sử dụng chương trình này, hãy chuyển bản đồ dưới dạng một chuỗi với các ký tự dòng mới hoặc với mỗi cấp được phân tách bằng khoảng trắng như trong ví dụ sau.

program-name.exe "+-----------+ |X          | |           | |           | |X         X| |           | |          X| |           | D           D +-----------+ "

+------+----+
|X     |    |
|    +D+-+  |
+----+   |  |
|X   | + D X|
|    | | +--+
|    | | | X|
+D---+ | +-D+
D      |    D
+------+----+

typedef int Q;typedef char R;typedef struct{Q x,y,v;}P;w,h,A,Y,Z,x,y,i,j,e,f,m,n,v;P*t,*u,*s;I(R*a,Q x,Q y,R c){a[x+y*w]=c;}G(Q*a,Q x,Q y){if(x>-1&&x<w&&y>-1&&y<h)return a[x+y*w];return-1;}J(Q*a,Q x,Q y,Q c){a[x+y*w]=c;}P*E(Q n,Q*a,Q*c){P*r=0;for(i=v=0;i<A;i++)if(a[i]==n)r=(P*)realloc(r,sizeof(P)*(v+1)),r[v].x=i%w,r[v].y=i/w,r[v].v=v,*c=++v;return r;}C(Q*a,Q x,Q y,Q b){return(G(a,x-1,y)==b)+(G(a,x+1,y)==b)+(G(a,x,y-1)==b)+(G(a,x,y+1)==b);}H(Q*a,Q b){P q[A],r[A];m=Y,n=0;for(i=0;i<Y;i++)q[i]=t[i];while(m){while(m){x=q[m-1].x,y=q[m-1].y,v=q[m-1].v;i=G(a,x,y);if(i!=b&&i!=1){for(f=-1;f<2;f++){for(e=-1;e<2;e++){i=G(a,x+e,y+f);if(i==0){J(a,x+e,y+f,v+8);r[n].x=x+e;r[n].y=y+f;r[n].v=v;n++;}else if(i>=8&&i!=v+8)J(a,x+e,y+f,b);}}}m--;}for(i=0;i<n;i++)q[i]=r[i];m=n;n=0;}}B(P p,Q*a,Q*b){for(i=m=n=0;i<A;i++)if(b[i]>-2)b[i]=-1;P q[A],r[A];q[0]=p,q[0].v=0,b[p.x+p.y*w]=0;while(m+1){while(m+1){x=q[m].x,y=q[m].y,v=q[m].v;for(f=-1;f<2;f++){for(e=-1;e<2;e++){if(e!=0&&f!=0||(x+e<0||x+e>=w||y+f<0||y+f>=h))continue;i=G(a,x+e,y+f);if(i!=7&&i!=1&&i!=0){j=3;if(i==4||i==5)j=1;if(x+e!=p.x&&y+f!=p.y)j++;Q*p=&b[x+e+(y+f)*w];if(*p!=-2&&(*p==-1||*p>v+j)){*p=v+j;if(i!=2)r[n].x=x+e,r[n].y=y+f,r[n].v=v+j,n++;}}}}m--;}for(i=0;i<n;i++){q[i]=r[i];}m=n-1,n=0;}}D(P S,P*T,Q n,P U,Q*a){Q m[A];Q x,y,v=0,c=0,d=1,d1=1;for(i=0;i<n;i++)T[i].v=0;for(i=0;i<A;i++)m[i]=-1;x=S.x,y=S.y;if(n==0){B(U,a,m);goto fin;}while(v<n){j=-1;for(i=0;i<n;i++)if(T[i].v==0)if(j==-1||abs(T[i].x-x)+abs(T[i].y-y)-(T[i].x==x)*!d*2-(T[i].y==y)*d*2<abs(T[j].x-x)+abs(T[j].y-y)-(T[j].x==x)*!d*2-(T[j].y==y)*d*2)j=i;T[j].v=1;B(T[j],a,m);fin:v++;c=m[x+y*w];while(c>0||c==-1){Q tx,ty;j=-1;for(f=-1;f<2;f++){for(e=-1;e<2;e++){if(e!=0&&f!=0)continue;if(x+e<0||x+e>=w||y+f<0||y+f>=h)continue;i=G(m,x+e,y+f);if(i>-1&&(i<c||c==-1)){if(j==-1||j>i||((e*d||f*!d)&&j==i)){j=i;tx=x+e,ty=y+f;d1=e!=0;}}}}J(m,x-1*!d1,y-1*d1,-2);J(m,x+1*!d1,y+1*d1,-2);d=d1;x=tx,y=ty,c=j;if(G(a,x,y)!=2)J(a,x,y,0);}for(f=0;f<h;f++)for(e=0;e<w;e++)if((i=G(a,e,f))>3&&i!=7)if(C(m,e,f,-2))J(a,e,f,5);if(v==n){B(U,a,m);goto fin;}}}main(Q c,R**v){R*a=v[1];w=strchr(a,'|')-a;h=(strchr(a+w,43)-a)/w+1;A=w*h;Q p[A];for(y=0;y<h;y++)for(x=0;x<w;x++){c=a[x+y*w];J(p,x,y,0);if(c==45||c=='|'||c==43)J(p,x,y,1);if(c==68)J(p,x,y,2);if(c==88)J(p,x,y,3);}t=E(3,p,&Y);u=E(2,p,&Z);H(p,5);for(c=0;c<Y;c++)for(y=-1;y<2;y++)for(x=-1;x<2;x++)if(G(p,t[c].x+x,t[c].y+y)>=4)J(p,x+t[c].x,y+t[c].y,7);for(y=1;y<h-1;y++)for(x=1;x<w-2;x++)if(G(p,x,y)==5)if(C(p,x,y,5)>2)J(p,x,y,4);s=E(4,p,&c);for(i=0;i<c;i++)s[i].v=0;for(y=1;y<h-1;y++)for(x=1;x<w-2;x++)if(G(p,x,y)>=8)if(C(p,x,y,5))J(p,x,y,4);i=u[0].x!=0;D(u[i],s,c,u[!i],p);for(y=0;y<h;y++){for(x=0;x<w;x++){i=0;if(G(p,x,y)>2){for(f=-1;f<2;f++)for(e=-1;e<2;e++)i+=G(p,x+e,y+f)==0;if(i>0)J(p,x,y,6);}}}free(s);for(i=0;i<A;i++)if(p[i]>=7||p[i]==4||p[i]==5)p[i]=0;for(y=0;y<h;y++){for(x=0;x<w-1;x++){if((x==0||x==w-2||y==0||y==h-1)&&G(p,x,y)!=2)J(p,x,y,1);}}H(p,1);P q[A],r[A];for(i=0;i<Y;i++){m=1,n=0;q[0]=t[i];while(m){while(m){x=q[m-1].x,y=q[m-1].y;for(f=-1;f<2;f++){for(e=-1;e<2;e++){if(e!=0&&f!=0)continue;c=G(p,x+e,y+f);if(c==6){if(G(p,x+e*2,y+f*2)==0){J(p,x+e,y+f,2);m=1,n=0;e=f=2;}}else if(c!=1&&c!=3&&c!=7){J(p,x+e,y+f,7);r[n].x=x+e;r[n].y=y+f;n++;}}}m--;}for(c=0;c<n;c++)q[c]=r[c];m=n;n=0;}}for(i=0;i<A;i++)if(p[i]==6)p[i]=1;R b[A];for(y=0;y<h;y++){for(x=0;x<w;x++){c=G(p,x,y);I(b,x,y,32);if(c==1){i=0;if(G(p,x,y-1)==1||G(p,x,y-1)==2)i|=1;if(G(p,x,y+1)==1||G(p,x,y+1)==2)i|=2;if(G(p,x-1,y)==1||G(p,x-1,y)==2)i|=4;if(G(p,x+1,y)==1||G(p,x+1,y)==2)i|=8;if(i==3)I(b,x,y,'|');else if(i==12)I(b,x,y,45);else I(b,x,y,43);}if(c==2)I(b,x,y,68);if(c==3)I(b,x,y,88);if(x==w-1)I(b,x,y,10);}}b[A-1]=0;puts(b);}

Tôi biết rằng đó là một thực hành tốt trong C để giải phóng bộ nhớ khi bạn hoàn thành nó, nhưng khi chơi golf, nó cần các byte không cần thiết. Bạn có thể lưu 16 byte bằng cách loại bỏ free(t);free(u);vào cuối chương trình. Ngoài ra, '\0'bằng 0, tiết kiệm thêm 3 byte.
Jonathan Frech

Nếu bạn thêm một cái gì đó như typedef int Q;và thay thế tất cả các lần xuất hiện intbằng Q, bạn có thể lưu thêm 44 byte.
Jonathan Frech
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.