파이썬 (2) 1,033 1,007 924 879 829 787 713 699 692 691 688 687 672 670 664 659 654 648 643 642 630 625 623 620 570 560 554 545 518 514 513 510 505 492 476 454 451 443 바이트
Riley 덕분에 6 바이트 절약
Adnan 덕분에 6 바이트 절약
이 질문은 1 년이 지났지 만 여전히 대답이 없으므로 시도해 볼 것이라고 생각했습니다.
n,i,o,u="\nI _";R=lambda x:range(1,x-1)
b=open(i).read()
s=b.split(n)
z=max(map(len,s))+3
a=[list(i+x.ljust(z,i))for x in[i]+s+[i]]
for x in R(len(a))*len(b):
A=a[x];B=a[x+1];C=a[x-1]
for y in R(z):
D=A[y-1:y+2];k=B[y];j=A[y+1]
if(i in[C[y],k]+D+(k==u)*B[y-1:y+2]or"V"==j)&(A[y]==o):A[y]=i
if"|"==A[y]==C[y]:A[y]={i:"|",j:">",A[y-1]:"<"}[i]
if[u]*3==D:A[y],B[y]={i:u+k,C[y]:"^"+k,k:" V"}[i]
print n.join(`y`[2::5]for y in a).replace(i,o)
온라인으로 사용해보십시오!
프로그램은 파일 이름이 지정된 테이블을 읽고 I테이블을 의자와 함께 인쇄합니다 std::out. 나는 많은 최첨단 사례에 대해 확신하지 못했기 때문에 최선의 판단 (최소한 노력을 기울인 것)을 취했지만 모든 테스트 사례를 통과 한 것으로 보입니다. 일부 출력은 정확히 일치하지 않지만 모두 동일한 수의 의자가 있습니다.
설명
첫 번째 줄은 미래에 바이트를 절약 할 몇 가지 정의를 설정합니다.
(나중에 읽을 수 있도록이 매크로의 압축을 풉니 다.)
n,i,o="\nI ";R=lambda x:range(1,x-1)
그런 다음 I이미 짧은 변수가 있으므로 몇 바이트를 절약하기 때문에 이름이 지정된 파일을 열 것 입니다.
b=open("I").read().split("\n")
줄 바꿈으로 분할하여 문자열 목록 (이미지의 행)을 만듭니다.
s=b.split(n)
그런 다음 가장 긴 줄의 길이를 찾아서 모든 줄을 해당 길이로 채울 수 있습니다. (우리는 약간의 추가 패딩이 필요하기 때문에 3을 추가합니다)
z=max(map(len,s))+3
그런 다음 실제 패딩을 수행 I하고 가장자리 주위 에 문자 테두리를 만듭니다 . 나중에 모양의 내부와 외부의 차이를 알려야하기 때문입니다. 또한 데이터 유형을 문자열 목록에서 문자 목록 (길이 1 문자열)으로 변경합니다.
a=[list("I"+x.ljust(z,"I"))for x in["I"]+s+["I"]]
다음 줄은 또 다른 바이트 절약 정의입니다.
(나는 또한 이것을 풀 것이다)
B=R(len(a))
이제 I캐릭터를 도형 외부의 모든 곳에 퍼 뜨리고 싶습니다 . 우리는 유사 세포 오토 마톤으로 이것을 할 수 있습니다. 각각 I은 인접한 문자로 퍼 집니다. 오토 마톤이 안정화 될 때까지 반복 할 수 있지만, 문자보다 더 많은 반복을 할 수 없으므로 b(원래 입력)의 모든 문자를 반복합니다.
for _ in b:
반복 할 때마다 2D리스트의 모든 문자를 넘기려고합니다 (가장 바깥 쪽 패딩 제외)
for x in range(1,len(a)-1):
A=a[x] #<--Another definition I will fill in for clarity
for y in range(1,z-1):
각 위치에 대해 다음 코드를 실행합니다.
if("I" in[a[x+1][y],a[x-1][y]]+a[x][y-1:y+2])&(a[x][y]==" "):a[x][y]=" "
이것을 분해하자.
우리는 &(비트 단위 and)로 구분 된 두 개의 조건이있는 if
첫 번째 I셀은 인접한 셀이 있는지 확인하고 두 번째 셀은 현재 셀이 a인지 확인합니다 " ". 이러한 조건을 통과하면 현재 셀을로 설정합니다 I.
모양의 바깥 쪽과 안쪽을 결정 했으므로 의자를 테이블 주위에 놓을 수 있습니다.
다시 한번 우리는 모든 셀을 반복합니다 (그리고 더 많은 속기를 설정합니다)
for x in range(1,len(a)-1):
A=a[x]
for y in range(1,z-1):
k=a[x+1][y]
이제 내가 가장 좋아하는 부분이 있습니다. 만약 당신이 나의 지루하고, 주로 정의에 기초한, 골프를 겪었다면, 나는 당신에게 멋진 영리한 골프의 좋은 보상을 줄 것입니다 (내가 그렇게 말하면).
파이썬에서 약간의 배경 :
파이썬에서는 사전 키를 두 번 할당하려고하면 후자가 할당됩니다. 예를 들어
>>> {1:"a",1:"b"}[1]
'b'
이 속성을 남용하여 현재 셀을 특정 문자에 할당합니다.
첫 번째 조건은
if["_"]*3==a[x][y-1:y+2]:a[x][y],a[x+1][y]={"I":"_"+a[x+1][y],a[x-1][y]:"^ ",a[x+1][y]:" V"}["I"]
셀이 가장자리가 3 _자인 경우 현재 셀과 그 아래의 셀을 다시 할당합니다. 로 오버로드 된 사전을 색인화 한 결과에이를 할당합니다 I. 먼저 기본값을 쌍으로 설정합니다. "I":"_"+a[x+1][y]변경 사항이 없으면 두 셀을 원래 값으로 다시 할당합니다. 다음으로 쌍을 추가합니다 a[x-1][y]:"^ ". 현재 셀 ( a[x-1][y]) 위의 셀 이로 채워져 있지 않으면 아무 것도하지 않습니다 (중요) I. 그 I안에 들어 있으면 현재 셀에 의자를 놓으라는 기본 설정을 무시합니다. 다음으로 현재 셀 아래에있는 셀로 이동합니다. 만약 그 셀이 I우리가 현재 지점 아래에 위로 향한 의자를 놓기 위해 다시 오버라이드 된다면 .
다음 조건은 조금 더 간단합니다
if"|"==a[x][y]==a[x-1][y]:a[x][y]={"I":"|",A[y+1]:">",A[y-1]:"<"}["I"]
현재 셀과 그 위의 셀이 모두 있는지 확인합니다 |. 그렇다면 사전을 설정했습니다.
사전의 첫 번째 쌍이 "I":"|"기본값을 설정합니다. 우리는 키에 액세스하려고하기 때문에 I경우 I는 다시 기본값으로 재 할당되지 않습니다 |(문자가 이미) 아무것도하지 않습니다.
우리는 두 개의 키를 추가합니다 A[y+1]:">",A[y-1]:"<". 두 셀 중 하나가 왼쪽과 오른쪽에 I있으면 현재 셀을 외부 방향을 가리키는 의자에 다시 할당합니다.
이제 출력 만하면됩니다. 그러나 우리는 단지 인쇄 할 수 없으며, 우리가 먼저해야 할 몇 가지 정리 작업이 있습니다. 우리는 문자열로 다시 변환하고 I우리가 만든 모든 것을 제거해야합니다 . 이것은 한 줄로 이루어집니다.
print "\n".join(`y`[2::5]for y in a).replace("I"," ")