Metin labirent çözücü


16

Stdin üzerinde bir labirent ve bir giriş noktası verildiğinde, stdout'ta çıkışa giden bir yol yazdıran bir program yazın. Programınız her labirent için önemsiz yolu (labirentin her noktasından geçen) üretmediği sürece herhangi bir yol kabul edilebilir.

Girişte duvarlar a #ile ve giriş noktası a ile işaretlenmiştir @. Tümü farklı oldukları sürece labirent ve çıktıdaki yolu çizmek için herhangi bir karakter kullanabilirsiniz.

Şunu varsayabilirsiniz:

  • Giriş ve çıkış noktaları girişin kenarlarındadır
  • Girişin her satırı aynı uzunlukta
  • Labirent çözülebilir ve döngü yok
  • Sadece bir çıkış noktası var

(Unicode) karakter sayısına göre en kısa çözüm kazanır.

Örnekler

(girişlerin boşlukla doldurulduğunu unutmayın)

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

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

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

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

Bitiş noktası için de bir karakter ekleyebilir miyim? Programımın ne zaman sona ereceğini bilmesi çok daha kolay olacaktır.
Peter Olson

Mısırın Peter: Tabii. Tüm yolu çizmek için aynı karakteri kullanmanız gerekmez, sadece çıktının geri kalanından ayırt edilebilir olmalıdır.
Lowjacker

Yanıtlar:


5

Yakut 1.9, 244 karakter

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

İki örnek için çıktı:

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

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

Düzenlemeler:

  • (247 -> 245) Inline e ve yeniden g olarak değiştirildi
  • (245 -> 249) Çıkış doğrudan girişin üzerindeyken bir hatayı düzeltin
  • (249 -> 246) Satır içi + basitleştirmeler
  • (246 -> 244) Her alanda yinelemenin daha kısa yolu

8

ISO C ( 384 373 368 karakter)

İşte benim C girişimim. Derlendi ve Mac OS X'te çalıştırıldı.

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

Birkaç test için örnek çıktı:

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

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

Sınırlamalar: Yalnızca 1000 karaktere kadar labirentler için geçerlidir, ancak bu kolayca artırılabilir. Malloc / remalloc'u rahatsız etmek yerine rastgele bir sayı seçtim.

Ayrıca, bu şimdiye kadar yazdığım en uyarı yüklü kod. 19 uyarı, ancak XCode kod vurgulamasıyla daha da fazla görünüyor. : D

DÜZENLEMELER:! = EOF yerine ~ kullanmak için printf yerine int kullanmak üzere düzenlendi ve test edildi. Yorumlar için teşekkürler!


9999 kullanabilirsiniz - aynı karakter sayısı
11:11

Aferin! Daha int önce " " işaretini atlayın mainve 4 karakter kaydedin. Ayrıca kullanmak putchar(*(s-1))yerine printf("%c",*(s-1))daha 4 kaydedin.
Casey

Ayrıca değiştirebilir 0xAtarafından 10ve !=tarafından ^.
Lowjacker

Daha da iyisi: ~while(~(c=getchar())
EOF'u

Ayrıca 'L' labirentinde yer alan L && guard'ı L ayarına bırakabilirim.
Jonathan Watmough

4

Python, 339 karakter

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)

Labirent aracılığıyla en kısa yolu oluşturur.

Örneğin labirentler için çıktı:

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

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

Neden N tarafından yapılan tüm toplama ve çıkarma işlemleri?
Lowjacker

10. satırdaki D [i + j] indekslemesinin negatif olmasını önler. Ve D [e + j] satır 12'de.
Keith Randall

1

Python - 510 421 karakter

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)

*Sağ alt köşede, ilk test durumunda (python 2.6.1) bir tane alıyorum . Düşüncesi olan var mı?
Lowjacker

@Lowjacker Teşekkürler, golf sırasında işe yaramış gibi görünen bir hata ekledim, ancak sadece test senaryoları için ve hatta zar zor: P
Juan

Güzel, şimdi çalışıyor. Ama hata ayıklamak için olduğunu print b,rprint (i,j)
varsayalım

1

Python 3 , 273 bayt

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,c in enumerate(g):print(end=[c,'+'][i in s])

Çevrimiçi deneyin!

Bir ASCII yolundaki en kısa rotayı bulmak için cevabımın limanı .

Kullanımları '#'başlangıç için, '*'sonu için, '@'duvara ve ' 'boş alan için. Burada fonksiyon q, labirentteki en kısa yolla tek boyutlu bir dizi döndüren bir yardımcı işlevdir. fDeğişken atanmadan işlev 4 bayt kısaltılabilir s. Bu inanılmaz derecede verimsizdir ve labirentteki her karakter için yol bulma işlevini çağırdığı için zaman aşımına uğrayacaktır.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.