Розв’яжіть зворотний лабіринт стрілки


14

Це "лабіринт стрілки":

  v      < 
>     v    
      >  ^ 
>         v
^ <       *

В *відзначає місце , де ви закінчите. Ваша мета - знайти, де починається лабіринт (отже, зворотний лабіринт). У цьому випадку це перший >у другому рядку.

  v------< 
S-+---v  | 
  |   >--^ 
>-+-------v
^ <       *

Зверніть увагу, що всі стрілки повинні бути використані. Також зауважте, що ви можете припустити, що лінії будуть прокладені пробілами однакової довжини.

Ваша програма повинна вводити лабіринт будь-яким розумним способом (stdin, з файлу, вікна повідомлень тощо), однак лабіринт повинен бути повністю неушкодженим. Наприклад, ви не можете вводити рядки, розділені комами; вхід повинен бути саме лабіринт.

Ви повинні вивести початок лабіринту будь-яким розумним способом. Наприклад, ви могли

  • вивести координати початку
  • виведіть весь лабіринт зі стрілкою старту, заміненою на S
  • вивести весь лабіринт усіма стрілками, за винятком запущеної стрілки (пробіл недоторканий!)
  • тощо.

Поки ви можете за своїм результатом сказати, яка стрілка є стрілкою старту, тоді це добре. Наприклад, вихід

"0"
"2"

це добре, незалежно від нових рядків і цитат, тому що ви все ще можете сказати, з чого почався.

Це , тому найкоротший код у байтах виграє.


Чи розумно вважати, що на кожній стрілці вказана лише одна стрілка, яка вказує на неї? Не буде екземпляра, де може бути декілька вихідних точок?
Денні

Чи є "старт лабіринту" стрілою, з якої один раз відвідується стрілка? Іншими словами, питання Денні + припущення, що немає циклів.
shiona

3
"ви не можете вводити рядки, розділені комами; вхід повинен бути саме лабіринтом." Це здається зайвим обмеженням, оскільки "саме лабіринт" вже фактично розмежований новими рядками між рядками. Навіщо розставляти пріоритети одного роздільника над іншим?
Джонатан Ван Матре

1
@Doorknob Це розумно, оскільки теоретично можна було закодувати цілий стислий розчин у «роздільниках». Однак я підозрюю, що обмеження вводить певний мовний упередження щодо певних мов. Що робити, якщо правило було "Рядки введення можуть бути обмежені будь-яким одним символом на ваш вибір. Усі рядки повинні бути обмежені одним і тим же символом."? Я думаю, що верхня межа корисна, оскільки вона встановлює домен, в якому ваша програма повинна працювати.
Джонатан Ван Матре

1
@Peter Це просто означає , що, наприклад, в вказує на , що не . Я відредагую більше матеріалів, коли сьогодні повернусь додому до комп’ютера. >v^>v^
Дверна ручка

Відповіді:


4

GolfScript, 55 байт

:&,,{&=42>},.{.&="><^v"?[1-1&n?~.~)]=:d;{d+.&=32=}do}%-

Демонстрація в Інтернеті

Передбачається, що всі вхідні рядки прокладені пробілами однакової довжини та розділені новими рядками. Виводить байтове зміщення стартової стрілки від початку вхідного рядка (наприклад, 12для прикладу лабіринт у виклику).

Зокрема, ця програма знаходить зміщення байтів усіх стрілок, на яких не вказана інша стрілка (якщо припустити, що всі стрілки вказують на стрілку або ціль; якщо це не відповідає дійсності, може виникнути дивна поведінка). За замовчуванням, якщо є декілька таких стрілок (які, за специфікацією, не мають бути можливими при дійсному введенні), їхні зміщення будуть просто об'єднані у висновку. Якщо ви хочете, ви можете додати n*до програми, щоб вони були розділені новими рядками.

Версія для де-гольфу з коментарями:

:&                     # save a copy of the input string in the variable "&"
,, { &= 42> },         # make a list of the byte offsets of all arrows 
.                      # duplicate the list and apply the following loop to it:
{
  .                    # make a copy of the original offset...
  &=                   # ...and get the corresponding character in the input
  "><^v" ?             # map the arrow character to integers 0 to 3, and...
  [ 1 -1 &n?~ .~) ]=   # ...map these to +1, -1, -len-1 or +len+1, where len is the...
  :d;                  # ...length of the first input line, and save result as "d"
  { d+ . &= 32= } do   # add d to the byte offset until another non-space is found
} %
-                      # subtract the resulting list of target offsets from the
                       # original list of arrow offsets; this should leave exactly
                       # one offset, which is left on the stack for output

1
Ви можете зберегти 3 символи, якщо ви вбудовуєте їх у рядок w.
Говард

@Howard: Так, я можу. Спасибі! Довелося перейменувати, zщоб &уникнути необхідності додаткового місця. OTOH, ?~.~)робить досить приємний смайлик. :-)
Ільмарі Каронен

5

GolfScript ( 101 100 байт)

n/:g,,{:&g=:r,,{&1$r='^v<>*'?70429 3base 2/=++}/}%{,4=},.{2<}%:&\{2/~\{[~2$~@+(@@+(\]&1$?)!}do\;}%^`

Вихід має форму, [[x y]]коли координати обидва базуються на 0.

Демонстрація в Інтернеті

Обробка проходить у дві фази: перша фаза перетворює лабіринт у масив [x y dx dy]кортежів; друга фаза відображає кожну стрілку / зірочку на стрілку / зірочку, на яку вона вказує. (Зірочки вважаються вказівними на себе). За визначенням проблеми, є рівно одна стрілка, яка відсутня в результаті цієї карти, і це рішення.


Я щойно вставляв свою відповідь, коли ви це публікували. У нас була одна і та ж ідея, але вам вдалося її успішно пограти в гольф. Хороший!
Вереос

@PeterTaylor Я не можу помітити, що він обробляє точку через справу правильно, що згадується в коментарях.
Говард

@Howard, я поняття не маю, що це за справа. Попросить роз'яснення.
Пітер Тейлор

Будь ласка, розмістіть приклад введення та виводу?
DavidC

@DavidCarraher, дивіться демонстрацію в Інтернеті. ;'STUFF'імітує подачу STUFFчерез stdin.
Пітер Тейлор

2

Mathematica 491 323

Безголовка з коментарями

Процедура починається від фінішу ("*"), знаходить стрілку, яка вказує на неї, і так далі до досягнення старту.

Функція, f [лабіринт].

(* positions of the arrowheads *)
aHeads[a_]:=Position[m,#]&/@{"^","v",">","<"}

(* position of the final labyrinth exit*)
final[a_]:=Position[a,"*"][[1]];


(* find arrowheads that point to the current location at {r,c} *)
aboveMe[{r_,c_},a_]:=Cases[aHeads[a][[2]],{r1_,c}/;r1<r]
belowMe[{r_,c_},a_]:=Cases[aHeads[a][[1]],{r1_,c}/;r1>r]
rightOfMe[{r_,c_},a_]:=Cases[aHeads[a][[4]],{r,c1_}/;c1>c]
leftOfMe[{r_,c_},a_]:=Cases[aHeads[a][[3]],{r,c1_}/;c1<c]

(*find the precursor arrowhead*)
precursor[{loc_,a_,list_:{}}]:=

(* end the search when the precursor has already been traversed or when there is no precursor *)
Which[MemberQ[list,loc],list,
loc=={},list,True,


(* otherwise find the next precursor *)

попередник [{Flatten [{flatMe [loc, a], belowMe [loc, a], rightOfMe [loc, a], leftOfMe [loc, a]}, 2], a, Prepend [список, loc]}]]

(* return the path through the maze from start to finish *)
f[maze_]:= precursor[{final[maze[[1]]],maze[[1]]}]

Гольф

f@z_:=Module[{p,h,m=z[[1]]},h@a_:=Position[a,#]&/@{"^","v",">","<","*"};
  p[{v_,a_,j_:{}}]:=Module[{r,c,x=Cases},{r,c}=v;
  Which[MemberQ[j,v],j,v=={},j,True,
  p[{Flatten[{x[h[a][[2]],{r1_,c}/;r1<r],x[h[a][[1]],{r1_,c}/;r1>r],
  x[h[a][[4]],{r,c1_}/;c1>c],x[h[a][[3]],{r,c1_}/;c1<c]},2],a,Prepend[j,v]}]]];
  p[{Position[m,"*"][[1]],m}]]

Приклад

Лабіринт. Кожна впорядкована пара містить рядок і стовпець комірки. Напр. {2, 3} позначає комірку в рядку 2, стовпець 3.

maze=Grid[Normal@ SparseArray[{{5, 5} -> "*",{1, 2} -> "v", {1, 5} -> "<",{2, 1} -> ">",
   {2, 3} -> "v",{3, 3} -> ">", {3, 5} -> "^",{4, 1} -> ">", {4, 5} -> "v",{5, 1} -> "^", 
   {5, 2} -> "<",{_, _} -> " "}]]

лабіринт


Вхідні дані

f[maze]

Вихід : шлях від початку до кінця.

{{2, 1}, {2, 3}, {3, 3}, {3, 5}, {1, 5}, {1, 2}, {5, 2}, {5, 1}, { 4, 1}, {4, 5}, {5, 5}}


Ваш формат введення невірний - "вхід повинен бути саме лабіринтом".
Дверна ручка

Тепер вхід - сам лабіринт.
DavidC

Я не дотримувався коду, але те, як ви вирішили "вхід зараз - лабіринт" , є цікавим! +1 ... кількість віруючих у "STDIN є універсальною" вражає.
Доктор Белісарій,

Я радий, що ти оцінив рішення проблеми введення.
DavidC

1

Я думаю, що я знайшов хороший спосіб вирішити це, але мені трапилось смоктати в гольф. Я думаю, це може бути ШЛОШО коротше, тому я збираюся пояснити свою ідею, щоб інші могли використовувати її, якщо вважають це гарним.

Якщо потрібно використовувати кожну стрілку, то всі стрілки будуть вказані іншою стрілкою, крім однієї, це наше рішення.

Це означає, що насправді нам не потрібно грати в лабіринт назад, але, починаючи з верхнього лівого, нам просто потрібно перевірити найближчу стрілку для кожного. Це справжня заставка для більших лабіринтів (адже вам не потрібно перевіряти всі чотири напрямки, а лише один).

Ось моє рішення:

PHP, 622 байти

$h=fopen("a.txt","r");$b=0;while(($z=fgets($h))!==false){$l[$b]=str_split($z,1);$b++;}$v=array("^","<","v",">");$s=array();for($i=0;$i<count($l);$i++){for($j=0;$j<count($l[0]);$j++){if(in_array($l[$i][$j],$v)){switch($l[$i][$j]){case"^":$c=$i-1;while($l[$c][$j]==" ")$c--;$s[]=$c.",".$j;break;case"v":$c=$i+1;while($l[$c][$j]==" ")$c++;$s[]=$c.",".$j;break;case"<":$c=$j-1;while($l[$i][$c]==" ")$c--;$s[]=$i.",".$c;break;case">":$c=$j+1;while($l[$i][$c]==" ")$c++;$s[]=$i.",".$c;break;}}}}for($i=0;$i<count($l);$i++){for($j=0;$j<count($l[0]);$j++){if(in_array($l[$i][$j],$v)){if(!in_array($i.",".$j,$s)){echo$i.",".$j;}}}}

Безголівки:

$h=fopen("a.txt","r");
$b=0;
while(($z=fgets($h))!==false) {
    $l[$b]=str_split($z,1);
    $b++;
}
//Input ends here
$v = array("^","<","v",">");
$s = array();
//Here i check every arrow, and save every pointed one in $s
for($i=0;$i<count($l);$i++){
    for($j=0;$j<count($l[0]);$j++){
        if(in_array($l[$i][$j],$v)){
            switch($l[$i][$j]) {
                case "^":
                    $c=$i-1;
                    while ($l[$c][$j]==" ")
                        $c--;
                    $s[]=$c.",".$j;
                    break;
                case "v":
                    $c=$i+1;
                    while ($l[$c][$j]==" ")
                        $c++;
                    $s[]=$c.",".$j;
                    break;
                case "<":
                    $c=$j-1;
                    while ($l[$i][$c]==" ")
                        $c--;
                    $s[]=$i.",".$c;
                    break;
                case">":
                    $c=$j+1;
                    while ($l[$i][$c]==" ")
                        $c++;
                    $s[]=$i.",".$c;
                    break;
            }
        }
    }
}
//I check if the arrow is in $s. If not, we have a solution.
for($i=0;$i<count($l);$i++){
    for($j=0;$j<count($l[0]);$j++){
        if (in_array($l[$i][$j],$v)){
            if (!in_array($i.",".$j,$s)){
                echo$i.",".$j;
            }
        }
    }
}

1

PHP - 492 байти

$r=split("\n",$m);$h=count($r);foreach($r as &$k)$k=str_split($k);$l=count($r[0]);$e=strpos($m,"*")+1-$h;$a=$x=$e%$l;$b=$y=floor(($e-$x)/$l);do{$c=0;for(;--$a>=0;){if($r[$b][$a]==">"){$x=$a;$c++;}if($r[$b][$a]!=" ")break;}$a=$x;for(;--$b>=0;){if($r[$b][$a]=="v"){$y=$b;$c++;}if($r[$b][$a]!=" ")break;}$b=$y;for(;++$a<$l;){if($r[$b][$a]=="<"){$x=$a;$c++;}if($r[$b][$a]!=" ")break;}$a=$x;for(;++$b<$h;){if($r[$b][$a]=="^"){$y=$b;$c++;}if($r[$b][$a]!=" ")break;}$b=$y;}while($c>0);echo "$x-$y";

Це рішення передбачає, що карту можна знайти в локальній змінній $m. Найкоротший метод, який я маю для проходження, це через $_GET: $m=$_GET['m'];у 14 байт. Нижче представлена ​​версія для нечіткості читання із змінною картою для ясності читання.

$m=<<<EOT
  v      < 
>     v    
      >  ^ 
>         v
^ <       * 
EOT;

$r=split("\n",$m);
$h=count($r);
foreach($r as &$k)
    $k=str_split($k);
$l=count($r[0]);

$e=strpos($m,"*")+1-$h;

$a=$x=$e%$l;
$b=$y=floor(($e-$x)/$l);
do{
$c=0;
for(;--$a>=0;)
    {
        if($r[$b][$a]==">"){$x=$a;$c++;}
        if($r[$b][$a]!=" ")break;
    }
$a=$x;
for(;--$b>=0;)
    {
        if($r[$b][$a]=="v")
            {
                $y=$b;
                $c++;
            }
        if($r[$b][$a]!=" ")break;

    }
$b=$y;
for(;++$a<$l;)
    {
        if($r[$b][$a]=="<")
            {
                $x=$a;
                $c++;
            }
        if($r[$b][$a]!=" ")break;
    }
$a=$x;
for(;++$b<$h;)
    {
        if($r[$b][$a]=="^")
            {
                $y=$b;
                $c++;
            }
        if($r[$b][$a]!=" ")break;
    }
$b=$y;
}while($c>0);
echo "$x-$y";

1

К, 281 277 258

{{$[&/x in*:'{{~"*"=x 1}{(s;k . s;k;s:*1_w@&(k ./:w:{{x@&x in y}[(*:'{(x[1]@x 0;x 1)}\[x;(z;y)]);i]}[(h!b,b,a,a:#k:x 2)m;(h!(0 1+;0 -1+;1 0+;-1 0+))m:x 1;x 0])in"*",h:"><v^")}\(x;y;z;x)}[*x;y .*x;y];*x;.z.s[1_x]y]}[i@&~(x ./:i::,/(!#x),/:\:!b::#*x)in" *";x]}

Ось більш рання версія, що не має волі

solve:{[x]
    //j - indices of all possible starting points
    //i - every index
    j::i@&~(x ./:i::,/(!a:#x),/:\:!b:#*x) in " *";

    h::">v<^";

    //d - dictionary mapping each directional character to
    //    increment/decerement it needs to apply to the x/y axis
    d::h!((::;1+);(1+;::);(::;-1+);(-1+;::));

    //e - dictionary mapping each directional character to
    //    the maximum number of moves it should make in a 
    //    given direction
    e::h!b,a,b,a;

    //f - function to produce the indices of each point that is 
    //    passed once we move in a certain direction from a 
    //    certain index
    f::{{x@&x in y}[(last'{(x[0];x[0]@'x 1)}\[x;(y;z)]);i]};

    //g - function that, given a starting and a direction,
    //    moves in that direction until hitting another directional
    //    character. It then moves in the new direction etc. until
    //    it reaches the end point -- *
    g::{[x;y;z]
        {[x]
            q:x 0;m:x 1; k:x 2;
            w:f[e m;d m;q];
            s:*1_w@&(k ./:w)in h,"*";
            m:k . s;
            (s;m;k;s)}\[{~"*"=x 1};(x;y;z;x)]};

    // recursive function that starts at the first possible starting point
    // and plots its way to the end. If all other potential starting points
    // have been touched in this path, then this is the correct starting point.
    // else, recursively call the function with the next possible starting point
    :{$[min "b"$j in last'g[*x;y . *x;y];*x;.z.s[1_x;y]]}[j;x]
  }

Повертає початкову точку, як x yдля 0 на основі індексів.

k)maze
"  v      < "
">     v    "
"      >  ^ "
">         v"
"^ <       *"
k)solve maze
1 0

1

Пітон 422

with open("m.txt","r") as f:m=f.read().split("\n")
p=[(v.find("*"),p) for p,v in enumerate(m) if "*" in v][0]
g=[]
def f(a):
    x,y=b,c=a
    for p,i in enumerate((lambda x:[l[x] for l in m])(x)):
        if i in "^>v<" and((p<y and i=="v")or(p>y and i=="^")):return b,p
    for p,i in enumerate(m[y]):
        if i in "^>v<" and((p<x and i==">")or(p>x and i=="<")):return p,c
while True:
    z=f(p)
    if z in g:break
    else:g.append(z);p=z
print p

Вхід знаходиться у файлі під назвою m.txt. Вихід є, (x, y)але якщо ви зміните останнє твердження про друк на print g, вихід буде складати список, як [(x, y), (x, y), ...]і всі кроки, щоб пройти від кінця до початку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.