Prison Architect, 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
가능한 해결 방법 : 통로 첫 번째 방
Matthew Roh

관련 벽을 구성 할 때 도움이 될 수 있습니다.
TheLethalCoder

1
내가 죄수 주위에 벽과 문을 직접 두는 것을 방해하는 이유는 무엇입니까?
Fels

죄송합니다. "한 글자 너비"입니다.
Fels

답변:


15

파이썬 2 , 2986 2881 2949 2135 2075 2071 1996 바이트

  • 105 바이트를 절약하고 표준 규칙을 준수하는 기능으로 프로그램을 구현했습니다. 밀 마법사의 탭과 공간 제안을 구현했습니다.
  • 버그 수정으로 68 바이트 추가
  • Halvard Hummel 덕분에 814 + 51 바이트가 절약되었습니다.
  • 9 + 4 바이트를 저장했습니다.
  • Outgolfer Erik 덕분에 4 바이트가 절약되었습니다.
  • ppperry의 제안으로 71 바이트를 절약했습니다.
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 아트 모양이 구현됩니다.

몇 시간 동안 글을 쓸 수있었습니다. 테스트 케이스 이외의 다른 감옥에서도 작동하기를 바랍니다. (모두 테스트 할 수는 없습니까?)


여러 수준의 들여 쓰기를 위해 공백과 탭을 번갈아 사용할 수 있습니다. (space = 1 들여 쓰기, tab = 2 들여 쓰기)
Wheat Wizard

1
또한 이것은 스 니펫입니다. 사전 초기화 된 변수 ( P) 에서 입력을 받는다는 의미 입니다. 허용되는 IO 형식이 아닙니다. input()함수를 사용 하거나 정의해야합니다.
밀 마법사

이것이 큰 코드 조각이기 때문에 골프로 볼 수있는 약 100 개의 작은 것들도 있습니다. 나는 그들을 모두 나열하지 않을 것이다. 그러나 당신이 그들을 통해 당신을 도울 수 있도록하려면 채팅에서 나를 핑 수 있습니다. 당신은 비교적 새로운 사용자이기 때문에 나는 당신이 파이썬 골프에 얼마나 익숙한 지 모르겠습니다. 아마도 당신은 여전히 ​​혼자서 골프를 치고 있습니다. :)
밀 마법사

여기 내가 본 몇 가지 트릭을 구현하는 더 짧은 버전이 있습니다. 골프를 치기 위해 가장 멀리 떨어져있는 것은 아닙니다. 알고리즘도 알지 못합니다. 그러나 약 300 바이트가 짧습니다. 그래도 여전히 스 니펫이므로이를 준수해야합니다.
밀 마법사

1
@HalvardHummel 목표에 도달했다; 우리는 2000 바이트 미만입니다!
Jonathan Frech

4

C, 3732 3642 바이트

나는 확실히 이것을 조금 더 골프 수 있지만, 그것은 꽤 좋은 시작입니다. 나는 처음에 내 접근 방식에 이름이 있다는 것을 몰랐으므로 @TehPers에게 연구에 이름을 줘서 외쳤다. 나는이 질문에 대한 도전을 확실히 즐겼다. :)

@Jonathan의 제안에서 -63 바이트. 또한 대체 chartypedef char R90 바이트의 총 자신의 ASCII 값이 100보다 작은를 모든 문자 리터럴을 교체

내 코드에 대한 간단한 설명.

  1. char 배열을 이상적인 정수 배열로 변환하십시오 (0은 공간, 1은 벽 등입니다)
  2. 사람들을 포인트로 사용하여 보로 노이 다이어그램 생성
  3. 교차점 (적어도 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);}

C에서 메모리를 다 사용하면 메모리를 비우는 것이 좋지만 골프를 칠 때 불필요한 바이트가 필요하다는 것을 알고 있습니다. free(t);free(u);프로그램 끝에서 간단히 제거 하여 16 바이트를 절약 할 수 있습니다. 또한 다른 3 바이트를 절약하는 '\0'것과 같습니다 0.
Jonathan Frech

같은 것을 추가하고 typedef int Q;모든 항목을 intQ바꾸면 다른 44 바이트를 저장할 수 있습니다.
Jonathan Frech
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.