텍스트 미로 해결사


14

stdin에 미로와 진입 점이 주어지면 stdout의 종료 경로를 인쇄하는 프로그램을 작성하십시오. 프로그램이 모든 미로에 대한 사소한 경로 (미로의 모든 지점을 통과하는)를 생성하지 않는 한 모든 경로를 사용할 수 있습니다.

입력에서 벽은로 표시되고 #진입 점 은로 표시됩니다 @. 미로와 경로를 모두 구별하기 만하면 어떤 문자를 사용해도됩니다.

다음과 같이 가정 할 수 있습니다.

  • 출입 지점은 입력 가장자리에 있습니다.
  • 입력의 모든 줄은 길이가 같습니다
  • 미로는 해결할 수 있고주기가 없습니다
  • 출구는 하나뿐입니다

(유니 코드) 문자 수에 의한 최단 솔루션이 승리합니다.

(입력은 공백으로 채워집니다)

####   
#  #   
@ #####
#     #
#      
#######

####
#  #
@*#####
#*    #
#******
#######

### ###################
###         #         #
##  #########      #  #
 #             #####  #
 ###############   #@##

###*###################
###*********#*********#
## *#########*     # *#
 # *********** #####**#
 ###############   #@##

엔드 포인트에 문자를 추가 할 수 있습니까? 내 프로그램이 언제 끝나야 하는지를 훨씬 쉽게 알 수 있습니다.
피터 올슨

@Peter Of The Corn : 물론입니다. 전체 경로를 그리는 데 동일한 문자를 사용할 필요는 없으며 나머지 출력과 구별 할 수 있어야합니다.
Lowjacker

답변:


5

루비 1.9, 244 자

l=*$<
i=l*""
e=[]
d=[1,-1,x=l[0].size,-x]
r=[f=9e9]*s=x*b=l.size;r[i=~/@/]=0
r.map{i.gsub(/ /){r[p=$`.size]=d.map{|u|p>-u&&r[u+p]||f}.min+1;e<<p if p%x%~-~-x*(p/-~x%~-b)<1}}
r[g=e.find{|i|r[i]<f}].times{i[g]=?*;g+=d.find{|l|r[g]>r[g+l]}}
puts i

두 가지 예에 대한 출력 :

####   
#  #   
@*#####
#*    #
#******
#######

###*###################
###*        #     *** #
## *######### *****#* #
 # ************#####* #
 ###############   #@##

편집 :

  • (247-> 245) e를 인라인하고 g로 이름을 바꿨습니다.
  • (245-> 249) 출구가 입구 바로 위에있을 때의 버그 수정
  • (249-> 246) 인라인 + 단순화
  • (246-> 244) 모든 필드를 반복하는 짧은 방법

8

ANSI C ( 384 373 368 자)

여기 내 C 시도가 있습니다. Mac OS X에서 컴파일 및 실행

m[9999],*r=m,*s=m,c,R=0,*a,L;
P(){while(*s++)putchar(*(s-1));}
C(int*l){if((l-s+2)%R==0||(l-s)%R==0||l-s<R||l>r-R)*l=42,P(),exit(0);}
e(int*l){if(*l==32)C(l),*l=42,e(l-1),*l=32,*l=42,e(l-R),*l=32,*l=42,e(l+1),*l=32,*l=42,e(l+R),*l=32;}
main(){while(~(c=getchar()))*r++=c,R=!R&&c==10?r-s:R,L=c==64?r-s-1:L;L%R==0&&e(s+L+1);(L+2)%R==0&&e(s+L-1);L<R&&e(s+L+R);e(s+L-R);}

몇 가지 테스트에 대한 샘플 출력 :

####   
#  #   
@*#####
#*****#
#    *#
#####*#

###*###################
###*        #******** #
##**#########**    #* #
 #*************#####* #
 ###############   #@##

제한 사항 : 최대 1000 자까지 미로에서만 작동하지만 쉽게 늘릴 수 있습니다. 나는 malloc / remalloc을 방해하지 않고 임의의 숫자를 골랐다.

또한 이것은 내가 작성한 가장 경고가 많은 코드입니다. XCode 코드 강조 표시로 훨씬 더 비슷해 보이지만 19 경고. :디

EDITS :! = EOF 대신 ~를 사용하고 printf 대신 putchar를 사용하도록 main에서 int를 삭제하도록 편집하고 테스트했습니다. 의견 주셔서 감사합니다!


9999를 사용할 수 있습니다. 같은 수의 문자입니다
Lowjacker

잘 했어! " int "을 생략하고 main4자를 저장하십시오. 4를 더 절약하기 위해 putchar(*(s-1))대신 사용하십시오 printf("%c",*(s-1)).
Casey

또한 대체 할 수있는 0xA10!=에 의해 ^.
Lowjacker

더 나은 : ~연산자를 사용하여 EOF를 확인할 수 있습니다 .while(~(c=getchar())
Lowjacker

또한 '@'의 미로 위치 인 L을 설정하면! L && 가드를 삭제할 수 있습니다.
Jonathan Watmough

4

파이썬, 339 자

import sys
M=list(sys.stdin.read())
L=len(M)
R=range(L)
N=M.index('\n')+1
D=2*L*[9e9]
D[M.index('@')+N]=0
J=(1,-1,N,-N)
for x in R:
 for i in[N+i for i in R if' '==M[i]]:D[i]=min(1+D[i+j]for j in J)
e=[i+N for i in R[:N]+R[::N]+R[N-2::N]+R[-N:]if 0<D[i+N]<9e9][0]
while D[e]:M[e-N]='*';e=[e+j for j in J if D[e+j]<D[e]][0]
print''.join(M)

미로를 통한 최단 경로를 생성합니다.

미로와 같은 출력 :

####   
#  #   
@*#####
#*    #
#******
#######

###*###################
###*        #     *** #
## *######### *****#* #
 # ************#####* #
 ###############   #@##

왜 N에 의한 모든 덧셈과 뺄셈?
Lowjacker

10 행의 인덱싱 D [i + j]가 음수가되지 않도록합니다. 12 번 라인의 D [e + j]
Keith Randall

1

파이썬 - (510 개) 421 문자

m=[]
i=raw_input
l=i()
x=y=-1
while l:
 if y<0:x+=1;y=l.find('@')
 m.append(list(l));l=i()
s=(x,y)
t={}
q=[s]
v={s:1}
while 1:
 try:(i,j),q=q[0],q[1:];c=m[i][j]
 except:continue
 if c==' 'and(i*j==0)|(i+1==len(m))|(j+1==len(m[0])):break
 for d,D in(-1,0),(0,-1),(1,0),(0,1):
  p=(i+d,j+D)
  if not p in v and'#'!=c:v[p]=0;q.append(p);t[p]=(i,j)
while(i,j)!=s:m[i][j]='*';i,j=t[(i,j)]
print'\n'.join(''.join(l)for l in m)

내가 받고 있어요 *첫 번째 테스트 케이스 (파이썬 2.6.1)에, 오른쪽 하단 모서리에. 이견있는 사람?
Lowjacker

@Lowjacker 고마워, 골프를 치는 동안 나는 그것이 작동하는 것처럼 보이게 만드는 버그를 추가했지만 테스트 케이스를 위해 간신히 간신히 보인다 : P
Juan

좋아요, 지금 작동합니다. 그러나 당신은 내가 디버깅하는 것으로 추정되는 print b,r과 를 꺼내는 것을 잊었습니다.)print (i,j)
Lowjacker

0

파이썬 3 , 275 바이트

import sys
def q(g,s=[]):w=len(g[0])+1;k='@'.join(g)+w*'@';*p,x=s or[k.find('#')];return'@'>k[x]and{x}-{*p}and[p,min((q(g,s+[x+a])or k for a in(-1,1,-w,w)),key=len)]['*'>k[x]]
g=''.join(sys.stdin.read());s=q(g.split('\n'))
for i in range(len(g)):print(end=[g[i],'+'][i in s])

온라인으로 사용해보십시오!

ASCII 도로에서 가장 짧은 경로 찾기에 대한 내 대답의 포트 .

용도 '#'스타트, '*'엔드, '@'벽 및 ' '빈 공간. 이 함수 q는 미로에서 가장 짧은 경로를 가진 1 차원 배열을 반환하는 도우미 함수입니다. f변수를 할당하지 않으면 기능 을 4 바이트 단축 할 수 있습니다 s. 이것은 엄청나게 비효율적이며 미로의 각 캐릭터에 대한 경로 찾기 기능을 호출하기 때문에 시간이 초과 될 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.