Arquitecto de la prisión, versión ASCII

42

Aquí hay un diagrama de una prisión con caracteres ASCII:

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

Las paredes están hechas de caracteres de tubería |, guiones -y pilares +para esquinas e intersecciones. También hay dos puertas marcadas con D(que siempre estarán en las paredes izquierda y derecha). La prisión está llena de gente aterradora marcada con X.

El objetivo es construir muros para satisfacer lo siguiente:

  1. Cada persona está en confinamiento solitario;
  2. Hay un corredor que corre entre las dos puertas;
  3. Cada celda contiene exactamente una puerta, que está conectada directamente al corredor principal;
  4. Todo el espacio en la prisión es utilizado por las celdas y el corredor;
  5. Cada celda contiene una persona (es decir, no hay celdas vacías).

El corredor es un camino único, no se ramifica y siempre tiene un carácter de ancho. Aquí hay una solución para la prisión anterior:

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

Puede suponer que cualquier prisión de entrada siempre tendrá una salida válida. Aquí hay algunas prisiones de entrada más, junto con posibles salidas:

+------------------------------+
|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--+ |
|                |
+----------------+
Ajenjo
fuente
44
Posible solución: camino primero a las habitaciones siguientes
Matthew Roh
Relacionado , podría ser útil al construir las paredes.
TheLethalCoder
1
¿Qué me impide poner paredes y una puerta directamente alrededor de cada prisionero (como en su segundo ejemplo) y declarar el resto del espacio como un corredor?
siente el
Lo sentimos, lo encontré: "un personaje de ancho".
siente el

Respuestas:

15

Python 2 , 2986 2881 2949 2135 2075 2071 1996 bytes

  • Guardado 105 bytes, implementó el programa como una función para cumplir con las normas estándar. Implementado la pestaña Asistente de trigo y sugerencia de espacio.
  • Se agregaron 68 bytes debido a la corrección de un error.
  • Guardado 814 + 51 bytes gracias a Halvard Hummel.
  • Guardado 9 + 4 bytes.
  • Guardado 4 bytes gracias a Erik the Outgolfer.
  • Guardado 71 bytes gracias a la sugerencia de 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 ")

Pruébalo en línea!

Fue golfing down significativamente; Sin embargo, todavía puede haber margen de mejora. Este código, sin embargo, resuelve todos los casos de prueba. No funciona de manera muy eficiente; Para grandes prisiones, el arquitecto puede tomarse su tiempo para resolverlo.
Utiliza un algoritmo de búsqueda de ruta simple para conectar las puertas y los prisioneros al corredor. Luego encapsula a todos los prisioneros y sus muros y empuja dichos muros en un espacio vacío hasta que se llena todo. Como paso final, se implementa la apariencia de arte ASCII.

Me tomó varias horas para escribir. Espero que también funcione en otras cárceles además de los casos de prueba. (No puedes probarlos a todos, ¿verdad?)

Jonathan Frech
fuente
Para múltiples niveles de sangría, puede alternar espacios y pestañas. (espacio = 1 sangría, pestaña = 2 sangrías)
Wheat Wizard
1
También este es un fragmento. Lo que significa que toma información de una variable preinicializada ( P). Este no es un formato IO permitido. Debe usar input()o definir una función.
Wheat Wizard
Siendo que este es un código tan grande, también veo alrededor de cien cosas más pequeñas que se pueden jugar al golf. No voy a enumerarlos a todos ahora. Pero si desea que lo ayude a superarlos, puede hacerme ping en el chat. Como usted es un usuario relativamente nuevo, no sé qué tan familiarizado está con el golf en python. Quizás sigas trabajando en jugar golf solo. :)
Wheat Wizard
Aquí hay una versión mucho más corta que implementa algunos de los trucos que vi. De ninguna manera es lo más lejos que se puede jugar golf, ni siquiera conozco tu algoritmo. Pero es unos 300 bytes más cortos. Sin embargo, todavía es un fragmento, por lo que deberá cumplirlo.
Wheat Wizard
1
@HalvardHummel Se alcanza el objetivo; ¡Tenemos menos de 2000 bytes!
Jonathan Frech
4

C, 3732 3642 bytes

Definitivamente podría jugar golf un poco más lejos, pero es un buen comienzo. Inicialmente no sabía que mi enfoque tenía un nombre, así que agradezca a @TehPers por darme un nombre para investigar. Definitivamente disfruté el desafío que me ofreció esta pregunta. :)

-63 bytes de las sugerencias de @ Jonathan. También he sustituido charcon typedef char Ry sustituye todos los caracteres literales que son menores que 100 con sus valores ASCII para un total de 90 bytes

Una explicación rápida de mi código.

  1. Convierta la matriz de caracteres en una matriz de enteros ideal (0 es espacio, 1 es pared, etc.)
  2. Genere el diagrama de Voronoi usando a las personas como puntos.
  3. Use las intersecciones (un 5 rodeado por al menos otros tres 5) como puntos de pivote para la ruta
  4. Cree el corredor utilizando un algoritmo de búsqueda de ruta sesgado direccionalmente (si va en una dirección, favorezca rutas que no cambien de dirección). También modifica la cuadrícula para que favorezca viajar al lado de un corredor ya hecho.
  5. Regenerar diagrama para colocar muros finales. Asegura que se use todo el espacio.
  6. Convierta el mapa nuevamente a una representación ASCII con el formato correcto e imprima.

Para usar este programa, pase el mapa como una cadena con caracteres de nueva línea o con cada nivel separado por un espacio como en el siguiente ejemplo.

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

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

código

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);}
Marcos
fuente
Sé que es una buena práctica en C liberar memoria cuando hayas terminado con ella, pero al jugar al golf requiere bytes innecesarios. Puede guardar 16 bytes simplemente eliminándolos free(t);free(u);al final de su programa. Además, '\0'es igual a 0guardar otros 3 bytes.
Jonathan Frech
Si agrega algo como typedef int Q;y reemplaza todas las apariciones de intcon Q, puede guardar otros 44 bytes.
Jonathan Frech