Текстовый лабиринт

14

Имея лабиринт на stdin и точку входа, напишите программу, которая печатает путь к выходу на stdout. Любой путь является приемлемым, если ваша программа не генерирует тривиальный путь (проходящий через каждую точку в лабиринте) для каждого лабиринта.

На входе стены отмечены символом a, #а точка входа - символом a @. Вы можете использовать любые символы для рисования лабиринта и пути в выводе, если они все различны.

Вы можете предположить, что:

  • Точки входа и выхода находятся по краям ввода
  • Каждая строка ввода имеет одинаковую длину
  • Лабиринт разрешим и не имеет циклов
  • Есть только одна точка выхода

Кратчайшее решение по количеству символов (Unicode) побеждает.

Примеры

(обратите внимание, что входы дополняются пробелами)

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

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

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

###*###################
###*********#*********#
## *#########*     # *#
 # *********** #####**#
 ###############   #@##
Lowjacker
источник
Могу ли я добавить символ для конечной точки? Для моей программы было бы намного легче знать, когда закончить.
Питер Олсон
@ Питер Кукурузы: Конечно. Вам не нужно использовать один и тот же символ для рисования всего пути, он просто должен отличаться от остальной части вывода.
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) Подчеркнул e и переименовал его в g
  • (245 -> 249) Исправлена ​​ошибка, когда выход был прямо над входом
  • (249 -> 246) Подкладка + упрощения
  • (246 -> 244) Более короткий способ итерации по каждому полю
Ventero
источник
8

ANSI C ( 384 373 368 символов)

Вот моя попытка Си. Скомпилировано и запущено на 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 из main, для использования ~ вместо! = EOF и putchar вместо printf. Спасибо за комментарии!

Джонатан Ватмоф
источник
Вы можете использовать 9999 - это то же самое количество символов
Lowjacker
Молодец! Опустите " int " перед mainи сохраните 4 символа. Также используйте putchar(*(s-1))вместо того, printf("%c",*(s-1))чтобы сохранить еще 4.
Кейси
Вы также можете заменить 0xAна 10и !=на ^.
Lowjacker
Еще лучше: вы можете использовать ~оператор для проверки 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?
Lowjacker
Это предотвращает отрицательную индексацию D [i + j] в строке 10. И D [e + j] в строке 12.
Кит Рэндалл
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)
Juan
источник
Я получаю *в правом нижнем углу, в первом тестовом случае (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. Это невероятно неэффективно и, скорее всего, истечет время ожидания, так как вызывает функцию поиска пути для каждого персонажа в лабиринте.

Jitse
источник