Тюремный Архитектор, версия ASCII


42

Вот схема тюрьмы с использованием символов ASCII:

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

Стены состоят из символов трубы |, тире -и столбов +для углов и пересечений. Есть также две двери, отмеченные D(которые всегда будут на левой и правой стенах). Тюрьма заполнена страшными людьми с пометкой X.

Цель состоит в том, чтобы построить стены, чтобы удовлетворить следующие требования:

  1. Каждый человек находится в одиночном заключении;
  2. Между двумя дверями проходит коридор;
  3. Каждая клетка содержит ровно одну дверь, которая напрямую связана с главным коридором;
  4. Все пространство в тюрьме используется камерами и коридором;
  5. Каждая ячейка содержит человека (то есть, нет пустых ячеек).

Коридор представляет собой единый путь, не разветвляется и всегда имеет ширину в один символ. Вот решение для тюрьмы выше:

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

Вы можете предположить, что любая входная тюрьма всегда будет иметь действительный выход. Вот еще несколько входных тюрем, а также возможные выходы:

+------------------------------+
|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
Возможное решение: путь первых комнат, следующий
Мэтью Ро,

Связанные , может быть полезно при строительстве стен.
TheLethalCoder

1
Что мешает мне поставить стены и дверь прямо вокруг каждого заключенного (как в вашем втором примере) и объявить остальное пространство коридором?
Fels

Извините, нашел это: "один символ в ширину".
Fels

Ответы:


15

Python 2 , 2986 2881 2949 2135 2075 2071 1996 байт

  • Сохранено 105 байт, реализована программа как функция для соответствия стандартным правилам. Реализована вкладка «Мастер пшеницы» и предложение пробела.
  • Добавлено 68 байт из-за исправления ошибки.
  • Сохранено 814 + 51 байт благодаря Halvard Hummel.
  • Сохранено 9 + 4 байта.
  • Сохранено 4 байта благодаря Эрику Аутгольферу.
  • Сохранено 71 байт благодаря предложению 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 ")

Попробуйте онлайн!

Это было в гольфе значительно; тем не менее, все еще может быть место для улучшения. Этот фрагмент кода, однако, решает все контрольные примеры. Не работает очень эффективно; для больших тюрем архитектор может не торопиться, чтобы выяснить это.
Использует простой алгоритм поиска пути, чтобы соединить обе двери и заключенных с коридором. Затем он заключает в капсулу всех заключенных и их стены и толкает указанные стены в пустом пространстве, пока все это не будет заполнено. В качестве последнего шага реализован внешний вид ASCII.

Мне понадобилось несколько часов, чтобы написать. Я надеюсь, что это также работает в других тюрьмах, кроме тестовых случаев. (Вы не можете проверить их все, не так ли?)


Для нескольких уровней отступов вы можете чередовать пробелы и табуляции. (пробел = 1 отступ, табуляция = 2 отступа)
Мастер пшеницы

1
Также это фрагмент. Это означает, что вы берете данные из предварительно инициализированной переменной ( P). Это недопустимый формат ввода-вывода. Вы должны использовать либо input()определить функцию.
Пшеничный волшебник

Учитывая, что это такой большой кусок кода, есть еще около сотни мелких вещей, которые я вижу, которые можно сыграть в гольф. Я не собираюсь перечислять их все сейчас. Но если вы хотите, чтобы я помог вам пройти через них, вы можете пинговать меня в чате. Поскольку вы относительно новый пользователь, я не знаю, насколько вы знакомы с питоном в гольф. Возможно, вы все еще работаете над игрой в гольф самостоятельно. :)
Пшеничный волшебник

Вот более короткая версия, в которой реализованы некоторые хитрости, которые я видел. Это ни в коем случае не самое далекое от игры в гольф, я даже не знаю ваш алгоритм. Но это примерно на 300 байт короче. Это все еще фрагмент, так что вам нужно будет заставить его соответствовать.
Пшеничный волшебник

1
@HalvardHummel Цель достигнута; мы под 2000 байтов!
Джонатан Фрех

4

C 3732 3642 байта

Я определенно мог бы сыграть в гольф немного дальше, но это довольно хорошее начало. Изначально я не знал, что у моего подхода есть имя, так что выкрикивайте @TehPers за то, что он дал мне имя для исследования. Я определенно наслаждался проблемой, которую предложил этот вопрос. :)

-63 байта из предложений @ Джонатана. Я также заменить charс typedef char Rи заменены все литералы символов, которые меньше , чем 100 с их значениями ASCII в общей сложности 90 байт

Быстрое объяснение моего кода.

  1. Преобразуйте массив char в идеальный массив целых чисел (0 - пробел, 1 - стенка и т. Д.)
  2. Сгенерируйте диаграмму Вороного, используя людей в качестве точек
  3. Используйте пересечения (5, окруженные по крайней мере тремя другими 5) в качестве опорных точек для пути
  4. Создайте коридор, используя алгоритм поиска пути смещения по направлению (если он идет в одну сторону, предпочитайте пути, которые не меняют направление). Он также изменяет сетку так, чтобы он предпочитал путешествовать рядом с уже созданным коридором.
  5. Восстановить схему для размещения окончательных стен. Гарантирует, что все пространство используется.
  6. Преобразуйте карту обратно в правильно отформатированное представление ASCII и распечатайте.

Чтобы использовать эту программу, передайте карту в виде строки с символами новой строки или с каждым уровнем, разделенным пробелом, как в следующем примере.

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);}

Я знаю, что в Си хорошая практика освобождать память, когда с ней покончено, но при игре в гольф это занимает ненужные байты. Вы можете сохранить 16 байтов, просто удалив free(t);free(u);в конце вашей программы. Кроме того, '\0'равно 0, экономя еще 3 байта.
Джонатан Фрех

Если добавить что - то вроде typedef int Q;и заменить все вхождения intс Q, вы можете сэкономить еще 44 байт.
Джонатан Фрех
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.