แก้ปัญหาเขาวงกตที่เป็นข้อความ


14

ให้เขาวงกตบน stdin และจุดเริ่มต้นเขียนโปรแกรมที่พิมพ์เส้นทางไปยังทางออกบน stdout เส้นทางใดก็ได้ที่ยอมรับได้ตราบใดที่โปรแกรมของคุณไม่สร้างเส้นทางที่ไม่สำคัญ (ผ่านทุกจุดในเขาวงกต) สำหรับเขาวงกตทุก ๆ

ในการป้อนข้อมูลผนังจะมีเครื่องหมายเป็นและจุดเข้าด้วย# @คุณสามารถใช้อักขระใด ๆ เพื่อวาดเขาวงกตและเส้นทางในผลลัพธ์ตราบใดที่พวกมันแตกต่างกัน

คุณอาจคิดว่า:

  • จุดเข้าและออกอยู่ที่ขอบของอินพุต
  • ทุกบรรทัดของอินพุตมีความยาวเท่ากัน
  • เขาวงกตสามารถแก้ไขได้และไม่มีรอบ
  • มีเพียงทางออกเดียวคือ

การแก้ปัญหาที่สั้นที่สุดด้วยการนับตัวอักษร (Unicode) จะชนะ

ตัวอย่าง

(โปรดทราบว่าอินพุตมีการบุด้วยช่องว่าง)

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

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

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

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

ฉันสามารถเพิ่มตัวละครสำหรับปลายทางได้หรือไม่? มันจะทำให้โปรแกรมของฉันรู้ได้ง่ายขึ้นว่าจะจบเมื่อไหร่
ปีเตอร์โอลสัน

@ Peter Of The Corn: แน่นอน คุณไม่จำเป็นต้องใช้ตัวอักษรเดียวกันเพื่อวาดเส้นทางทั้งหมด แต่จะต้องแยกความแตกต่างจากส่วนที่เหลือของเอาต์พุต
Lowjacker

คำตอบ:


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

เอาต์พุตสำหรับตัวอย่างสองตัวอย่าง:

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

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

การแก้ไข:

  • (247 -> 245) Inlined e และเปลี่ยนชื่อเป็น g
  • (245 -> 249) แก้ไขข้อผิดพลาดเมื่อทางออกอยู่เหนือทางเข้าโดยตรง
  • (249 -> 246) Inline + การทำให้เข้าใจง่าย
  • (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);}

เอาต์พุตตัวอย่างสำหรับการทดสอบสองสามข้อ:

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

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

ข้อ จำกัด : ใช้งานได้เฉพาะกับเขาวงกตที่มีความยาวไม่เกิน 1,000 ตัวอักษร แต่สามารถเพิ่มได้อย่างง่ายดาย ฉันเพิ่งเลือกหมายเลขที่กำหนดเองแทนที่จะไปสนใจ malloc / remalloc

นอกจากนี้นี่คือรหัสเตือนภัยที่ฉันเคยเขียน 19 คำเตือนถึงแม้จะดูเหมือนว่ามากขึ้นด้วยการเน้นรหัส XCode : D

แก้ไข: แก้ไขและทดสอบเพื่อปล่อย int จาก main เพื่อใช้ ~ แทน! = EOF และ putchar แทน printf ขอบคุณสำหรับความคิดเห็น!


คุณสามารถใช้ 9999 ได้ - เป็นจำนวนอักขระเท่ากัน
Lowjacker

เยี่ยมมาก! ละเว้น " int " ก่อนหน้าmainและบันทึก 4 อักขระ ใช้putchar(*(s-1))แทนprintf("%c",*(s-1))การบันทึกอีก 4 รายการ
Casey

นอกจากนี้คุณยังสามารถแทนที่0xAโดย10และโดย!= ^
Lowjacker

ยิ่งไปกว่านั้น: คุณสามารถใช้~โอเปอเรเตอร์เพื่อตรวจสอบ EOF:while(~(c=getchar())
Lowjacker

ฉันยังสามารถดรอป! L&& ผู้พิทักษ์ในการตั้งค่า L, ตำแหน่งในเขาวงกตของ '@'
Jonathan Watmough

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
Lowjacker

มันป้องกันการจัดทำดัชนี D [i + j] ในบรรทัด 10 จากการลบ และ D [e + j] ในบรรทัดที่ 12
Keith Randall

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

@ Lowjacker ขอบคุณดูเหมือนว่าในขณะที่เล่นกอล์ฟฉันได้เพิ่มบั๊กที่ทำให้มันดูเหมือนว่ามันใช้งานได้ แต่สำหรับกรณีทดสอบและแม้แต่แทบจะไม่: P
Juan

ดีมันใช้งานได้แล้ว แต่คุณลืมที่จะออกไปprint b,rและprint (i,j)ซึ่งผมเข้าใจได้สำหรับการแก้จุดบกพร่อง :)
Lowjacker

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เป็นฟังก์ชั่นผู้ช่วยที่ส่งกลับอาร์เรย์หนึ่งมิติที่มีเส้นทางที่สั้นที่สุดในเขาวงกต ฟังก์ชั่นfจะสั้นลง 4 sไบต์โดยไม่ได้กำหนดตัวแปร สิ่งนี้ไม่มีประสิทธิภาพอย่างไม่น่าเชื่อและน่าจะหมดเวลาเนื่องจากเรียกว่าฟังก์ชันการค้นหาเส้นทางสำหรับตัวละครแต่ละตัวในเขาวงกต

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.