Ters ok labirentini çözme


14

Bu bir "ok labirenti" dir:

  v      < 
>     v    
      >  ^ 
>         v
^ <       *

*İşaretleri Eğer bitecek nokta. Amacınız labirentin başladığı yeri bulmaktır (dolayısıyla ters labirent). Bu durumda, >ikinci satırdaki ilk .

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

Tüm okların kullanılması gerektiğini unutmayın. Ayrıca, çizgilerin eşit uzunlukta boşluklarla doldurulacağını varsayabilirsiniz.

Programınız labirenti makul bir şekilde girmelidir (stdin, bir dosyadan, mesaj kutusundan vb.), Ancak labirent tamamen sağlam olmalıdır . Örneğin, virgülle ayrılmış satırları giremezsiniz; girdi tam olarak labirent olmalıdır.

Labirentin başlangıcını makul bir şekilde vermelisiniz. Örneğin,

  • başlangıç ​​koordinatlarını çıktılar
  • labirentin tamamını çıkış oku ile değiştirin. S
  • labirentin tamamını çıkış oku hariç tüm oklarla çıkarın (boşluk bozulmamış!)
  • vb.

Çıktınız tarafından hangi okun başlangıç ​​oku olduğunu söyleyebildiğiniz sürece, o zaman sorun değil. Örneğin,

"0"
"2"

yeni satırlardan ve alıntılardan bağımsız olarak iyidir, çünkü yine de başlangıcın nerede olduğunu söyleyebilirsiniz.

Bu , bu yüzden bayttaki en kısa kod kazanacak.


Her okun kendisine işaret eden bir ok daha olduğunu varsaymak mantıklı mıdır? Birden fazla başlangıç ​​noktasının olabileceği bir örnek olmayacak mı?
Danny

"Labirentin başlangıcı" birbirinden okunan bir ok mu? Başka bir deyişle danny'nin sorusu + varsayımı döngü yoktur.
shiona

3
"virgülle ayrılmış satırları giremezsiniz; giriş tam olarak labirent olmalıdır." Bu gereksiz bir kısıtlama gibi görünüyor, çünkü "tam olarak labirent" zaten fiilen satırlar arasındaki yeni satırlarla sınırlanmış durumda. Neden bir sınırlayıcıyı diğerine göre önceliklendirin?
Jonathan Van Matre

1
@Doorknob Bu, teorik olarak "sınırlayıcılar" daki sıkıştırılmış bir çözümün tamamını kodlayabildiğinden mantıklıdır. Ancak, kısıtlamanın belirli dillere karşı belirli bir dilsel önyargı getirdiğinden şüpheleniyorum. Kural "Giriş satırları seçtiğiniz herhangi bir karakterle sınırlandırılabilir . Tüm satırlar aynı karakterle sınırlandırılmalıdır " olsaydı ne olurdu ? Üst sınır yararlı olduğunu düşünüyorum, çünkü programınızın çalışması gereken bir etki alanı oluşturur .
Jonathan Van Matre

1
Örneğin,, Bu sadece araçlarla @Peter işaret ediyor , değil . Bugün bir bilgisayara geri döndüğümde daha fazla şeyi düzenleyeceğim. >v^>v^
Kapı tokmağı

Yanıtlar:


4

GolfScript, 55 bayt

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

Çevrimiçi demo

Tüm giriş satırlarının aynı uzunlukta boşluklarla doldurulduğunu ve satırsonu ile ayrıldığını varsayar. Girdi dizesinin başlangıcından itibaren başlangıç ​​okunun bayt uzaklığını çıktılar (örneğin 12, sınamadaki örnek labirent için).

Özellikle, bu program diğer okları gösteren tüm okların bayt kaymalarını bulur (tüm okların bir oku veya hedefi gösterdiğini varsayarsak; bu doğru değilse garip davranışlar oluşabilir). Varsayılan olarak, bu tür birkaç ok varsa (spesifikasyon başına, geçerli girişte mümkün olmamalıdır), ofsetleri sadece çıktıda birleştirilecektir. İsterseniz n*, programa yeni satırlarla ayrılması için programa ekleyebilirsiniz .

Yorumların kaldırıldığı sürüm:

:&                     # 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
Satır içi iseniz 3 karakter kaydedebilirsiniz w.
Howard

@Howard: Ha, öyle yapabilirim. Teşekkürler! Yine de, fazladan bir alana ihtiyaç duymamak için yeniden adlandırmak zzorunda &kaldı. OTOH, ?~.~)oldukça hoş bir surat yapar. :-)
Ilmari Karonen

5

GolfScript ( 101 , 100 bayt)

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

Çıktı, [[x y]]koordinatların her ikisinin de 0-tabanlı olduğu biçimdedir .

Çevrimiçi demo

İşleme iki aşamada gerçekleşir: ilk aşama labirenti bir dizi [x y dx dy]tuple haline getirir ; ikinci aşama her ok / yıldız işaretini işaret ettiği ok / yıldız işaretiyle eşleştirir. (Yıldızların kendilerini işaret ettiği kabul edilir). Sorunun tanımına göre, bu haritanın sonucu olmayan tam olarak bir ok var ve çözüm bu.


Bunu gönderirken cevabımı yapıştırıyordum. Aynı fikrimiz vardı, ama başarılı bir şekilde golf oynamayı başardınız. Güzel!
Vereos

@PeterTaylor Yorumlarda belirtildiği gibi noktadan noktaya doğru işlediğini göremiyorum .
Howard

@ Ancak, bu davanın ne olduğu hakkında hiçbir fikrim yok. Açıklama talep edecektir.
Peter Taylor

Girdi ve çıktınıza bir örnek gönderir misiniz?
DavidC

@DavidCarraher, çevrimiçi demoya bakın. stdin yoluyla ;'STUFF'tedariki simüle eder STUFF.
Peter Taylor

2

Mathematica 491 323

Yorum yapılmamış

Prosedür bitişten ("*") başlar, onu gösteren oku bulur ve böylece başlangıca ulaşana kadar devam eder.

İşlev, f [labirent].

(* 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 *)

haberci [{Düzleştir [{aboveMe [loc, a], aşağıdaMe [loc, a], rightOfMe [loc, a], leftOfMe [loc, a]}, 2], a, Prepend [liste, loc]}]]

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

golfed

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}]]

Misal

Labirent. Sıralı her çift bir hücrenin satırını ve sütununu içerir. Örneğin, {2, 3} satır 2, sütun 3'teki hücreyi belirtir.

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} -> "<",{_, _} -> " "}]]

Labirent


Giriş

f[maze]

Çıktı : Baştan sona yol.

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


Giriş biçiminiz yanlış - "giriş tam olarak labirent olmalıdır".
Kapı tokmağı

Girdi şimdi labirentin kendisi.
DavidC

Ben kodu takip etmedim, ama "giriş artık labirent" şey çözme yolu komik! +1 ... "STDIN evrenseldir" e inananların sayısı şaşırtıcıdır.
Dr. belisarius

Giriş sorununun çözümünü takdir ettiğiniz için memnunum.
DavidC

1

Ben bunu çözmek için iyi bir yol buldum, ama ben golf emmek oldu. Sanırım bu WAY daha kısa olabilir, bu yüzden fikrimi açıklayacağım, böylece diğerleri iyi buluyorlarsa bunu kullanabilirler.

Her okun kullanılması gerekiyorsa, tüm oklar, bizim çözümümüz olan biri hariç başka bir okla işaretlenecektir.

Bu, labirenti geriye doğru oynamamız gerekmediği anlamına gelir, ancak sol üstten başlayarak her biri için en yakın sivri oku kontrol etmemiz gerekir. Bu, daha büyük labirentler için gerçek bir ağrı kesicidir (çünkü dört yönü de kontrol etmek zorunda değilsiniz, sadece bir tane).

İşte benim çözümüm:

PHP, 622 bayt

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

Ungolfed:

$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 bayt

$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";

Bu çözüm haritanın yerel değişken içinde bulunabileceğini varsayar $m. Geçmek için sahip olduğum en kısa yöntem $_GET: $m=$_GET['m'];14 bayt. Okuma netliği için değişkenli haritaya sahip ungolfed versiyon aşağıda verilmiştir.

$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

K, 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]}

İşte daha eski, çözülmemiş bir versiyon

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]
  }

Başlangıç ​​noktasını x y0 tabanlı endekslerde olduğu gibi döndürür .

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

1

Python 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

Girdi adlı bir dosyada m.txt. Çıktı, (x, y)ancak son baskı ifadesini olarak değiştirirseniz print g, çıktı sondan [(x, y), (x, y), ...]başlayarak tüm adımlara benzer bir liste olacaktı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.