Pemecah Labirin Menurun

9

Labirin menurun diberikan sebagai serangkaian baris spasi yang dipisahkan digit dari 0 hingga 9 inklusif, ditambah satu "S" dan satu "X", di mana S menunjukkan awal dan X menunjukkan finish. Di labirin menurun, Anda hanya dapat pergi ke ruang yang berdekatan dengan Anda di utara, selatan, timur, atau barat (tanpa diagonal), dan Anda hanya dapat pergi ke ruang dengan nilai kurang dari atau sama dengan nilai yang Anda sedang aktif.

Program harus mengeluarkan jalur untuk bernavigasi melalui labirin dalam format yang sama dengan input, hanya semua ruang yang dilintasi harus memiliki "." di dalamnya, dan semua ruang yang belum dikunjungi harus memiliki "#" di dalamnya. Sel awal dan akhir juga harus menyimpan "S" dan "X" masing-masing. Anda dapat mengasumsikan selalu ada solusi untuk labirin.

Input contoh:

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

Contoh output:

. . . . # # S . #
. # # . . # # . .
. # # # . # # # .
. # # # . # # # .
. . X # . . . . .
Luke D
sumber
3
Bisakah Anda pindah ke dan dari Sdan Xke segala arah? Apakah labirin selalu terpecahkan?
Calvin Hobbies
Juga, dapatkah kita berasumsi bahwa semua baris memiliki panjang yang sama? Dan, hanya untuk memperjelas, sebuah "digit" sarana tunggal desimal digit dari 0ke 9inklusif, kan?
Ilmari Karonen
1
@ Calvin Ya, Anda dapat pindah ke dan dari S dan X ke segala arah. Labirin diasumsikan dapat dipecahkan.
Luke D
1
@IImari Ya, semua baris memiliki panjang yang sama, dan ya, "digit" adalah satu digit dari 0 hingga 9 inklusif.
Luke D

Jawaban:

3

JavaScript (ES6) 219

Suatu fungsi yang mengembalikan benar atau salah. Solusinya (jika ditemukan) adalah output pada konsol. Itu tidak mencoba untuk menemukan solusi optimal.

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)

Tidak diserang sampai mati dan menjelaskan lebih dari yang dibutuhkan

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
}

Uji di Firefox / konsol 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')

Keluaran

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

true  
edc65
sumber
Kami tampaknya berbagi kode saling pengertian yang tidak terduga.
seequ
1
@ Seleg, mengapa tidak sebening kristal? Saya akan menambahkan penjelasan besok
edc65
@Sieg lebih mudah dipahami?
edc65
Memang bisa dipahami.
seequ
4

C # - 463

Menerima input melalui STDIN, dan harus menghasilkan jalur yang optimal, diuji untuk kasus uji yang diberikan, tetapi tidak sebaliknya. Anggap selalu ada solusi.

Saya agak terburu-buru, saya punya tenggat waktu dalam 7 jam, tapi ini sepertinya terlalu menyenangkan untuk dilewatkan. Saya juga tidak berlatih. Ini bisa sangat memalukan jika ini salah, tapi cukup layak golf.

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

Kode dengan komentar:

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
    }
}
VisualMelon
sumber