テキスト迷路ソルバー


14

stdinの迷路とエントリポイントが与えられたら、stdoutの出口へのパスを出力するプログラムを作成します。プログラムが迷路ごとに(迷路内のすべてのポイントを通過する)簡単なパスを生成しない限り、どのパスでも構いません。

入力では、壁は#で、エントリポイントはでマークされ@ます。出力で迷路とパスを描画するために、それらがすべて明確である限り、任意の文字を使用できます。

あなたはそれを仮定するかもしれません:

  • 入口点と出口点は入力の端にあります
  • 入力のすべての行は同じ長さです
  • 迷路は解決可能であり、サイクルはありません
  • 出口は1つのみ

(Unicode)文字数による最短の解決策が優先されます。

(入力にはスペースが埋め込まれることに注意してください)

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

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

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

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

エンドポイントにキャラクターを追加することもできますか?私のプログラムがいつ終了するかを知るのがずっと簡単になります。
ピーターオルソン

@Peter Of The Corn:もちろんです。パス全体を描画するのに同じ文字を使用する必要はありません。出力の残りの部分と区別できる必要があります。
ロージャッカー

回答:


5

Ruby 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

2つの例の出力:

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

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

編集:

  • (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に煩わされるのではなく、任意の数字を選んだだけです。

また、これは私がこれまでに書いた中で最も警告が多いコードです。19個の警告がありますが、XCodeコードの強調表示ではさらに多くの警告が表示されます。:D

編集:メインからintをドロップするように編集およびテストし、!= EOFの代わりに〜を使用し、printfの代わりにputcharを使用します。コメントをありがとう!


9999を使用できます-同じ文字数です
-Lowjacker

よくやった!「int 」の前mainを省略して、4文字を保存します。putchar(*(s-1))代わりにprintf("%c",*(s-1))を使用して、さらに4つ保存します。
ケーシー

また、置き換えることができます0xAによって10および!=によって^
ロージャッカー

さらに良い:~オペレーターを使用してEOFを確認できますwhile(~(c=getchar())
。– Lowjacker

また、「@」の迷路の場所であるLの設定に!L &&ガードをドロップすることもできます。
ジョナサンワトマフ

4

Python、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によるすべての加算と減算が必要なのはなぜですか?
ロージャッカー

行10のインデックスD [i + j]が負にならないようにします。12行目のD [e + j]
キースランドール

1

Python- 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)

私は取得しています*最初のテストケース(のpython 2.6.1)で、右下の隅に。何かご意見は?
ロージャッカー

@Lowjackerありがとう、ゴルフ中に動作するように見えるバグを追加したようですが、テストケースだけで、それでもかろうじて:P
11年

いいですね、今は動作します。しかし、あなたprint b,rprint (i,j)、私がデバッグのためだと
思わ

0

Python 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.