Downhill Maze Solver


9

เขาวงกตลงเขาให้เป็นชุดของแถวของช่องว่างที่คั่นหลักจาก 0 ถึง 9 รวมทั้งหนึ่ง "S" และ "X" หนึ่งที่ S หมายถึงการเริ่มต้นและ X หมายถึงการเสร็จสิ้น ในเขาวงกตที่ตกต่ำคุณสามารถไปยังพื้นที่ที่อยู่ติดกับคุณทางทิศเหนือทิศใต้ทิศตะวันออกหรือทิศตะวันตก (ไม่มีเส้นทแยงมุม) และคุณอาจไปที่ช่องว่างที่มีค่าน้อยกว่าหรือเท่ากับค่าที่คุณ กำลังเปิดอยู่

โปรแกรมควรแสดงเส้นทางเพื่อนำทางผ่านเขาวงกตในรูปแบบเดียวกับอินพุตเฉพาะพื้นที่ที่ถูกสำรวจทั้งหมดควรมี "" ในช่องว่างเหล่านั้นและช่องว่างที่ไม่ได้เข้าชมควรมี "#" อยู่ด้วย เซลล์เริ่มต้นและจุดสิ้นสุดควรเก็บ "S" และ "X" ไว้ตามลำดับ คุณสามารถสันนิษฐานได้ว่าเขามีทางออกให้เขาวงกตเสมอ

อินพุตตัวอย่าง:

3 3 3 3 2 1 S 8 9
3 1 1 3 3 0 6 8 7
1 2 2 4 3 2 5 9 7
1 2 1 5 4 3 4 4 6
1 1 X 6 4 4 5 5 5

ตัวอย่างผลลัพธ์:

. . . . # # S . #
. # # . . # # . .
. # # # . # # # .
. # # # . # # # .
. . X # . . . . .

3
คุณสามารถย้ายไปและกลับจากSและไปXในทิศทางใด? เขาวงกตสามารถแก้ไขได้เสมอหรือไม่
งานอดิเรกของ Calvin

นอกจากนี้เราสามารถสมมติว่าแถวทั้งหมดมีความยาวเท่ากันได้หรือไม่ และเพียงเพื่อชี้แจงเป็น "หลัก" หมายความว่าเดียวทศนิยมหลักจาก0การ9รวมใช่มั้ย?
Ilmari Karonen

1
@ Calvin ใช่คุณสามารถย้ายไปและกลับจาก S และ X ในทิศทางใดก็ได้ เขาวงกตที่สันนิษฐานว่าจะแก้ไขได้
ลุค D

1
@IImari ใช่ทุกแถวมีความยาวเท่ากันและใช่ "หลัก" คือตัวเลขเดียวตั้งแต่ 0 ถึง 9
ลุค D

คำตอบ:


3

JavaScript (ES6) 219

ฟังก์ชันส่งคืนจริงหรือเท็จ วิธีแก้ปัญหา (ถ้าพบ) เป็นผลลัพธ์บนคอนโซล มันไม่ได้พยายามหาทางออกที่ดีที่สุด

f=o=>(r=(m,p,w=0,v=m[p])=>
v>':'
  ?console.log(' '+m.map(v=>v<0?'#':v,m[f]='X').join(' '))
  :v<=w&&[1,-1,y,-y].some(d=>r([...m],d+p,v),m[p]='.')
)(o.match(/[^ ]/g).map((v,p)=>v>'S'?(f=p,0):v>':'?v:v<'0'?(y=y||~p,v):~v,y=0),f)

Ungolfedไปสู่ความตายและอธิบายมากกว่าที่จำเป็น

f=o=>{
  var r = ( // recursive search function
    m, // maze array (copy of)
    p, // current position
    w  // value at previous position
  )=> 
  {
    var v = m[p]; // get value at current position
    if (v == 'S') // if 'S', solution found, output and return true
    {
      m[f] = 'X'; // put again 'X' at finish position
      m = m.map(v => { // scan array to obtain '#'
        if (v < 0) // a numeric value not touched during search
          return '#'
        else  
          return v  
      }).join(' '); // array to string again, with added blanks (maybe too many)
      console.log(' '+m) // to balance ' '
      return true; // return false will continue the search and find all possible solutions
    }
    if (v <= w) // search go on if current value <= previous (if numeric, they both are negative)
    {
      m[p]='.'; // mark current position 
      return [1,-1,y,-y].some(d=>r([...m], d+p, v)) // scan in all directions
    }
    // no more paths, return false and backtrack
    return false
  }

  var f, // finish position (but it is the start of the search)
      y = 0; // offset to next/prev row
  o = o.match(/[^ ]/g) // string to char array, removing ' 's
  .map((v,p) => // array scan to find f and y, and transform numeric chars to numbers 
   {  
     if (v > 'S') // check if 'X'
     {
       f = p;
       return 0; // 'X' position mapped to min value
     }
     if (v > ':') // check if 'S'
       return v; // no change
     if (v < '0') // check if newline
     {
       if (!y) y = ~p; // position of first newline used to find y offset
       return v; // no change
     }
     return ~v; // map numeric v to -v-1 so have range (-1..-10)
   })

  return r(o, f, 0) // start with a fake prev value
}

ทดสอบในคอนโซล Firefox / FireBug

f('3 3 3 3 2 1 S 8 9\n3 1 1 3 3 0 6 8 7\n1 2 2 4 3 2 5 9 7\n1 2 1 5 4 3 4 4 6\n1 1 X 6 4 4 5 5 5')

เอาท์พุต

. . . . # # S . #   
. # # . . # # . .   
. # # # . # # # .   
. # # # . # # # .   
. . X # . . . . .  

true  

ดูเหมือนว่าเราจะแบ่งปันรหัสที่ไม่สามารถหยั่งรู้ได้
seequ

1
@ เห็นทำไมไม่ชัด ๆ ฉันจะเพิ่มคำอธิบายในวันพรุ่งนี้
edc65

@ เห็นชัดมากขึ้น?
edc65

หยั่งถึงแน่นอน
Seequ

4

C # - 463

ยอมรับอินพุตผ่าน STDIN และควรสร้างเส้นทางที่ดีที่สุดทดสอบสำหรับกรณีทดสอบที่กำหนด แต่ไม่ใช่อย่างอื่น สมมติว่ามีทางออกเสมอ

ฉันกำลังรีบหน่อยฉันมีกำหนดส่งภายใน 7 ชั่วโมง แต่นี่ดูเหมือนจะสนุกมากเกินไปที่จะพลาด ฉันก็ไม่ได้ฝึก มันอาจเป็นเรื่องที่น่าอายมากหากเกิดข้อผิดพลาด แต่มันก็สมเหตุสมผลพอสมควร

using C=System.Console;class P{static void Main(){var S=C.In.ReadToEnd().Replace("\r","").Replace('X','+');int s=S.IndexOf('S'),e=S.IndexOf('+'),w=S.IndexOf('\n')+1,L=S.Length,i,j=L;var K=new int[L];for(K[s]=s+2;j-->0;)for(i=0;i<L;i+=2){System.Action<int>M=z=>{if((z+=i)>=0&z<L&&S[z]<=S[i]&K[z]<1&K[i]>0&(i%w==z%w|i/w==z/w))K[z]=i+1;};M(2);M(-2);M(w);M(-w);}for(w=e;w!=s+1;w=i){i=K[w]-1;K[w]=-1;}for(;++j<L;)C.Write(j%2<1?K[j]<0?j==s?'S':j==e?'X':'.':'#':S[j]);}}

รหัสที่มีความคิดเห็น:

using C=System.Console;

class P
{
    static void Main()
    {
        var S=C.In.ReadToEnd().Replace("\r","").Replace('X','+'); // read in the map, replace X with + because + < 0
        int s=S.IndexOf('S'),e=S.IndexOf('+'),w=S.IndexOf('\n')+1,L=S.Length,i,j=L; // find start, end, width, length

        var K=new int[L]; // this stores how we got to each point as loc+1 (0 means we havn't visited it)

        for(K[s]=s+2; // can't risk this being 0
            j-->0;) // do L passes
            for(i=0;i<L;i+=2) // each pass, look at every location
            {
                // if a whole load of bouds checks, point new location (i+z) at i
                System.Action<int>M=z=>{if((z+=i)>=0&z<L&&S[z]<=S[i]&K[z]<1&K[i]>0&(i%w==z%w|i/w==z/w))K[z]=i+1;};
                // try and move in each direction
                M(2);
                M(-2);
                M(w);
                M(-w);
            }

        for(w=e;w!=s+1;w=i) // find route back
        {
            i=K[w]-1; // previous location
            K[w]=-1; // set this so we know we've visited it
        }

        for(;++j<L;) // print out result
            C.Write(j%2<1?K[j]<0?j==s?'S':j==e?'X':'.':'#':S[j]); // if K < 0, we visit it, otherwise we don't
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.