Yokuş aşağı Labirent Çözücü


9

Bir yokuş aşağı labirent, 0 ila 9 dahil olmak üzere bir dizi boşlukla ayrılmış basamak dizisi, artı bir "S" ve bir "X" olarak verilir; burada S, başlangıcı ve X, bitişi gösterir. Yokuş aşağı bir labirentte, yalnızca kuzey, güney, doğu veya batıya bitişik olan bir alana gidebilirsiniz (köşegenler olmadan) ve yalnızca sizin değerinizden daha düşük veya değere eşit boşluklara gidebilirsiniz. şu anda açık.

Program labirentte girişle aynı formatta gezinmek için bir yol çıkarmalı, sadece tüm çapraz boşluklar "." ve görünmeyen tüm alanların içinde "#" bulunmalıdır. Başlangıç ​​ve bitiş hücreleri de sırasıyla "S" ve "X" değerlerini korumalıdır. Labirente her zaman bir çözüm olduğunu varsayabilirsiniz.

Örnek girdi:

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

Örnek çıktı:

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

3
Herhangi bir yönde Sve Xherhangi bir yönde hareket edebilir misiniz ? Labirent her zaman çözülebilir mi?
Calvin'in Hobileri

Ayrıca, tüm satırların aynı uzunlukta olduğunu varsayabilir miyiz? Ve sadece açıklığa kavuşturmak için, bir "basamak" ile kapsayıcı arasındaki tek bir ondalık basamak anlamına gelir , değil mi? 09
Ilmari Karonen

1
@Calvin Evet, herhangi bir yönde S ve X'e gidip gelebilirsiniz. Labirentin çözülebilir olduğu varsayılır.
Luke D

1
@IImari Evet, tüm satırlar aynı uzunlukta ve evet, "basamak" 0 ila 9 dahil tek bir basamaktır.
Luke D

Yanıtlar:


3

JavaScript (ES6) 219

True veya false döndüren bir işlev. Çözelti (bulunursa) konsoldan çıkar. En uygun çözümü bulmaya çalışmaz.

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)

Öldürülmedi ve gereğinden fazla açıkladı

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 konsolunda test edin

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

Çıktı

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

true  

Karşılıklı kod anlaşılmazlığı paylaşıyor gibi görünüyoruz.
seequ

1
@Sieg neden, berrak değil mi? Yarın bir açıklama ekleyeceğim
edc65

@ Daha fazla yağlanabilir mi?
edc65

Gerçekten kandırılabilir.
seequ

4

C # - 463

STDIN yoluyla girişi kabul eder ve verilen test durumu için test edilmiş, ancak başka şekilde değil, optimal bir yol üretmelidir. Her zaman bir çözüm olduğunu varsayar.

Biraz acelem var, 7 saat içinde bir son teslim tarihim var, ama bu kaçırmak için çok eğlenceli görünüyordu. Ben de pratik dışındayım. Bu yanlış giderse çok utanç verici olabilir, ancak makul 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]);}}

Yorumları içeren kod:

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