แก้เขาวงกตลูกศรย้อนกลับ


14

นี่คือ "เขาวงกตลูกศร":

  v      < 
>     v    
      >  ^ 
>         v
^ <       *

*เครื่องหมายจุดที่คุณจะเสร็จสิ้น เป้าหมายของคุณคือการหาที่เขาวงกตเริ่มต้น (เพราะฉะนั้นเขาวงกตกลับ) ในกรณีนี้มันเป็นครั้งแรก>ในบรรทัดที่สอง

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

โปรดทราบว่าต้องใช้ลูกศรทั้งหมด นอกจากนี้โปรดทราบว่าคุณสามารถสันนิษฐานได้ว่าเส้นจะถูกเติมด้วยช่องว่างให้มีความยาวเท่ากัน

โปรแกรมของคุณต้องป้อนเขาวงกตในลักษณะที่เหมาะสม (stdin จากไฟล์กล่องข้อความ ฯลฯ ) อย่างไรก็ตามเขาวงกตจะต้องไม่บุบสลายอย่างสมบูรณ์ ตัวอย่างเช่นคุณไม่สามารถป้อนบรรทัดที่คั่นด้วยเครื่องหมายจุลภาค การป้อนข้อมูลจะต้องตรงเขาวงกต

คุณต้องแสดงจุดเริ่มต้นของเขาวงกตด้วยวิธีที่สมเหตุสมผล ตัวอย่างเช่นคุณสามารถ

  • ส่งออกพิกัดของการเริ่มต้น
  • เอาท์พุทเขาวงกตทั้งหมดด้วยลูกศรเริ่มต้นแทนที่ด้วย S
  • เอาท์พุทเขาวงกตทั้งหมดด้วยลูกศรทั้งหมดยกเว้นลูกศรเริ่มลบออก (ช่องว่างเหมือนเดิม!)
  • เป็นต้น

ตราบใดที่คุณสามารถบอกได้ว่าลูกศรไหนเป็นลูกศรเริ่มจากนั้นก็โอเค ตัวอย่างเช่นผลลัพธ์ของ

"0"
"2"

ไม่เป็นไรไม่ว่าบรรทัดใหม่และราคาจะเป็นยังไงก็ตามคุณยังสามารถบอกได้ว่าจุดเริ่มต้นนั้นอยู่ที่ไหน

นี่คือดังนั้นโค้ดที่สั้นที่สุดเป็นไบต์จะเป็นผู้ชนะ


มีเหตุผลหรือไม่ที่จะสมมติว่าลูกศรแต่ละตัวมีลูกศรชี้ไปที่ลูกศรชี้เท่านั้น? จะไม่มีตัวอย่างที่อาจมีจุดเริ่มต้นหลายจุด
แดนนี่

"จุดเริ่มต้นของเขาวงกต" คือลูกศรจากการเยี่ยมชมลูกศรซึ่งกันและกันเมื่อหนึ่งครั้งหรือไม่ ในคำอื่น ๆ คำถาม + สมมติฐานของแดนนี่ไม่มีลูป
shiona

3
"คุณไม่สามารถป้อนบรรทัดที่คั่นด้วยเครื่องหมายจุลภาค; อินพุตต้องเป็นเขาวงกต" ดูเหมือนว่าจะเป็นข้อ จำกัด ที่ไม่จำเป็นเนื่องจาก "เขาวงกต" นั้นถูกคั่นด้วยความจริงแล้วโดยการขึ้นบรรทัดใหม่ระหว่างแถว เหตุใดจึงจัดลำดับความสำคัญตัวคั่นหนึ่งมากกว่าอีกตัว
Jonathan Van Matre

1
@Doorknob นั้นสมเหตุสมผลเนื่องจากในทางทฤษฎีสามารถเข้ารหัสโซลูชันที่ถูกบีบอัดทั้งหมดใน "ตัวคั่น" อย่างไรก็ตามฉันสงสัยว่าข้อ จำกัด นี้จะแนะนำอคติทางภาษาบางอย่างกับภาษาบางภาษา จะเกิดอะไรขึ้นถ้ากฎคือ "อินพุตแถวอาจถูกคั่นด้วยอักขระหนึ่งตัวที่คุณเลือกแถวทั้งหมดต้องถูกคั่นด้วยอักขระเดียวกัน "? ฉันคิดว่าขอบเขตบนมีประโยชน์เพราะมันสร้างโดเมนที่โปรแกรมของคุณต้องทำงาน
Jonathan Van Matre

1
@ Peter นั่นก็หมายความว่าตัวอย่างเช่นในชี้ไปไม่ได้ ฉันจะแก้ไขสิ่งต่าง ๆ เพิ่มเติมเมื่อฉันกลับบ้านที่คอมพิวเตอร์ในวันนี้ >v^>v^
Doorknob

คำตอบ:


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 ถ้าคุณ winline
Howard

@Howard: อืมดังนั้นฉันสามารถ ขอบคุณ! ต้องเปลี่ยนชื่อzเป็น&เพื่อหลีกเลี่ยงการต้องการพื้นที่เพิ่มเติมแม้ว่า OTOH ?~.~)ทำให้รอยยิ้มที่ดีงาม :-)
Ilmari Karonen

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]tuples; เฟสที่สองจะแม็พลูกศร / ดอกจันแต่ละอันกับลูกศร / ดอกจันที่ชี้ไป (เครื่องหมายดอกจันถูกพิจารณาให้ชี้ไปที่ตัวเอง) ตามคำนิยามของปัญหามีลูกศรหนึ่งอันที่ไม่ได้อยู่ในผลลัพธ์ของแผนที่นี้และนั่นคือทางออก


ฉันเพิ่งวางคำตอบของฉันในขณะที่คุณโพสต์นี้ เรามีความคิดเดียวกัน แต่คุณสามารถเล่นกอล์ฟได้สำเร็จ ทำได้ดีนี่!
Vereos

@PeterTaylor ฉันไม่สามารถเห็นว่ามันจัดการจุดผ่านกรณีได้อย่างถูกต้องซึ่งถูกกล่าวถึงในความคิดเห็น
Howard

@Howard ฉันไม่ทราบว่ากรณีนี้คืออะไร จะขอคำชี้แจง
Peter Taylor

คุณช่วยโพสต์ตัวอย่างของอินพุตและเอาต์พุตของคุณได้ไหม
DavidC

@DavidCarraher ดูตัวอย่างออนไลน์ ;'STUFF'จำลองการจัดหาSTUFFผ่าน stdin
Peter Taylor

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

สารตั้งต้น [{แผ่ [{aboveMe [loc, a], bottomMe [loc, a], rightOfMe [loc, a], leftOfMe [loc, a]}, 2], a, prepend [list, 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}}


รูปแบบการป้อนข้อมูลของคุณไม่ถูกต้อง - "การป้อนข้อมูลจะต้องตรงเขาวงกต"
Doorknob

การป้อนข้อมูลตอนนี้เขาวงกตเอง
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;}}}}

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 ไบต์

$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

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

นี่คือรุ่นก่อนหน้านี้ที่ไม่ดี

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

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

m.txtการป้อนข้อมูลที่อยู่ในไฟล์ที่เรียกว่า เอาต์พุตเป็น(x, y)แต่ถ้าคุณเปลี่ยนคำสั่ง print ล่าสุดprint gเป็นเอาต์พุตจะเป็นรายการที่เหมือนกับ[(x, y), (x, y), ...]ขั้นตอนทั้งหมดที่จะได้รับตั้งแต่ต้นจนจบ

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