Bir Buz Labirenti Çöz


19

Buz labirentleri, Pokémon Gold ve Silver'taki çıkışlarından bu yana Pokémon oyunlarının en sevdiğim zımbalarından biri oldu . Göreviniz bu tür sorunları çözen bir program yapmak olacaktır.

Buz labirentleri, adından da anlaşılacağı gibi buzdan oluşur. Oyuncu buz üzerinde bir yönde hareket ettiğinde, bir engelle çarpışana kadar bu yönde hareket etmeye devam edecektir. Serbestçe hareket ettirilebilen ve üzerinde herhangi bir oyuncunun hareket etmesini durduracak toprak da vardır. Son engel taştır. Taş, oyuncu ile aynı alanı kaplayamaz ve oyuncu onun içine taşınmaya çalışırsa, hareket etmeden önce durur.

3 döşeme tipinin (Buz, Toprak ve Taş) her biri için 3 ayrı değer içeren, liste listesi veya satırsonu ile ayrılmış bir dize gibi iki boyutlu bir değer kabı alırsınız. Ayrıca, labirentte bir başlangıç ​​ve hedef koordinatını belirten iki çift (veya başka bir eşdeğer iki değer kabı) alırsınız. Bunlar sıfır veya biri endekslenmiş olabilir.

Yürütüldüğünde oyuncunun sonuna gelmesine neden olacak bir hareket listesi (N, E, S, W üzerine bir bijection ile 4 farklı değer) vermelisiniz.

Girdinin labirent çevresinde her zaman kapalı bir taş çevresi olacaktır, bu yüzden labirentten çıkan oyuncu hakkında endişelenmenize gerek yoktur

Bu bu yüzden en az bayt kazanır

Test Durumları

Burada .buzu temsil ~edecek, toprağı Otemsil edecek ve bir taşı temsil edecek. Koordinatlar 1 endekslenir. Çözümdeki her harf, o harfle başlayan yönü temsil eder (örneğin N= Kuzey)


Giriş

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

Çıktı

N

Giriş

OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO

Start : 15,12
End   : 16,8

Çıktı

N,W,N,E,N,E,S,W,N,W,S,E,S,E,N,E,N

Giriş

OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO

Start : 2,2
End   : 14,3

Çıktı

E,S,S,W,N,E,N

Giriş

OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO

Start : 2,2
End   : 11,11

Çıktı

E,E,E,E,E,S,S,E,N,W,S,E,N,N,N

Girdinin her zaman en az bir geçerli çözümü olacak mı?
Pavel

@Pavel Bunu kabul edebilirsiniz.
Buğday Sihirbazı

Test senaryoları (satır, sütun) veya (sütun, satır) mı? 1 veya 0 endekslendi mi? Levha kenarları duvar olarak sayılıyor mu?
MildlyMilquetoast


2
@busukxuan Labirentte kalıcı olarak sıkışıp kalabilir (bkz. testcase 1)
Wheat Wizard

Yanıtlar:


4

Mathematica, 247 bayt

(p=x#[[##&@@x]];m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};e=Flatten[Table[#->c,{c,a@#}]&/@g,1];Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]])&

Satır kesmeleri ile:

(
p=x#[[##&@@x]];
m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c];
g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];
a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}};
e=Flatten[Table[#->c,{c,a@#}]&/@g,1];
Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]
)&

Benim asıl fikrim, buz ve toprak konumlarını, yasal hareketlere karşılık gelen yönlendirilmiş kenarları olan bir grafikte düğümler olarak göstermek, sonra kullanmaktı FindPath. Yasal hamleleri belirlemenin kolay ve çözüm bulmanın zor olduğu düşünülebilir. Benim için tam tersi oldu. Kenarların nasıl hesaplanacağına dair önerilere açık.

İlk argüman #, 0buzu 1temsil eden, toprağı 2temsil eden ve taşı temsil eden bir 2D dizidir .

İkinci argüman #2ve üçüncü argüman #3sırasıyla formdaki başlangıç ​​ve bitiş noktalarıdır {row,column}.

3 bayt özel kullanım karakter U+F4A1temsil \[Function].

açıklama

p=x#[[##&@@x]];

Form ve çıktıların plistesini alan bir işlevi tanımlar ; yani, bu koordinattaki buz / toprak / taş değeri.x{row,column}#[[row,column]]

m={c,v}Switch[p[c+v],0,m[c+v,v],1,c+v,_,c]

mBir başlangıç ​​konumu cve yön vektörü alan vve nerede bitireceğinizi yinelemeli olarak belirleyen bir işlevi tanımlar . Eğer c+vbuz, o zaman bu yüzden döndüren, o noktadan itibaren kaydırmaya devam m[c+v,v]. Eğer c+vtoprak olduğunu, o zaman taşımak c+vve durdurma. Aksi takdirde ( c+vtaş veya sınırların dışındaysa) hareket etmezsiniz. Bunun yalnızca buz veya toprak pozisyonlarında çağrılması amaçlandığını unutmayın.

g=Cases[Array[List,Dimensions@#],c_/;p@c<2,{2}];

gBuz ve toprak pozisyonlarının listesini tanımlar ( pküçüktür 2).

a=cm[c,#]&/@{{1,0},{-1,0},{0,1},{0,-1}}; 

Bir fonksiyon tanımlar a, bir başlangıç pozisyonu alır cve döner hareket eden sonuçları {1,0}, {-1,0}, {0,1}ve {0,-1}yön. Biraz fazlalık olabilir. Yine, bu cbuz veya toprağa karşılık gelir.

e=Flatten[Table[#->c,{c,a@#}]&/@g,1];

eYasal hareketleri temsil eden yönlendirilmiş kenarların listesini tanımlar . İçindeki her konum #için g, #->cher cgiriş için kenar tablosunu hesaplayın a@#. Sonra her pozisyon için bir alt liste olacağımızdan #, ilk seviyeyi düzleştiriyorum. Bazı halkalar ve çoklu kenarlar olabilir.

Normalize/@Differences@FindPath[Graph[e],#2,#3][[1]]

Graph[e]düğümlerin yasal pozisyonlar (buz veya toprak) olduğu ve kenarların yasal hareketleri (muhtemelen bir taşa çarpması ve hareket etmemesi) temsil ettiği grafiktir. Daha sonra kullanmak FindPathbir yolunu bulmak için #2hiç #3bir düğüm listesi olarak temsil etti. Yana FindPathbirden fazla yolu bulmak için ek argümanlar alabilir kullanıyorum ilk elemanı almak, böylece sonuç gerçekte tek bir yolu içeren bir liste olacak [[1]]. Sonra Differenceskoordinatları ve Normalizeonları birbirini izlerim . Böylece yukarı {-1,0}, aşağı {1,0}, sağ {0,1}ve sol {0,-1}.

Test senaryoları

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin


4

JavaScript (ES6) 180 183

(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

BFS kullanarak , bu ilgili sorunu çözmek için yaptığım gibi

Giriş
Labirent haritası, toprak için ve taş için Oveya buz için 8'den küçük herhangi bir sıfır olmayan basamak (çok iyi görünüyor) kullanan çok satırlı bir dizedir . Başlangıç ​​ve bitiş konumu sıfır tabanlıdır.087

Çıktı
Bir ofset listesi, burada -1 W, 1 E, negatif -1'den küçük Nve pozitif 1'den büyükS

Daha az golf

(m,[x,y],[t,u])=>{
  o=~m.search`\n`
  s=[[x-y*o,[]]]
  k=[]
  for(i=0; [p,l]=s[i++], k[p]=1, t-u*o != p;)
  {
    [-1,o,1,-o].map(d=>(
      M=p=>+m[p+=d] ? m[p]<8 ? M(p) : p : p-d,
      q=M(p),
      k[q]||s.push([q,[...l,d]])
    ))
  }
  return l
}

Ölçek

Solve=
(m,[x,y],[t,u],o=~m.search`
`,s=[[x-y*o,[]]],k=[])=>eval("for(i=0;[p,l]=s[i++],k[p]=t-u*o-p;)[-1,o,1,-o].map(d=>k[q=(M=p=>+m[p+=d]?m[p]<8?M(p):p:p-d)(p)]||s.push([q,[...l,d]]));l")

function Go(maze) {
  var map = maze.textContent;
  var [sx,sy, dx,dy] = map.match(/\d+/g)
  --sx, --sy // zero based
  --dx, --dy // zero based
  map = map.split('\n').slice(1).join('\n') // remove first line
  var result = Solve(map.replace(/\./g, 7).replace(/~/g, 8), [sx,sy], [dx,dy])
  S.textContent = result
  Animate(maze, map, result, sx, sy)
}

function Display(maze, map, pos) {
  var row0 = maze.textContent.split('\n')[0]
  map = [...map]
  map[pos] = '☻'
  maze.textContent = row0+'\n'+map.join('')
}

function Animate(maze, map, moves, x, y) {
  console.log('A',moves)
  var offset = map.search('\n')+1
  var curPos = x + offset * y
  var curMove = 0
  var step = _ => {
    Display(maze, map, curPos)
    if (curMove < moves.length) 
    {
      curPos += moves[curMove]
      if (map[curPos] == 'O')
      {
        curPos -= moves[curMove]
        ++curMove
      }  
      else 
      {
        if (map[curPos] == '~') {
          ++curMove
        }
      }
      setTimeout(step, 100)
    }
    else
      setTimeout(_=>Display(maze,map,-1),500)
  }
  step()
}
td { 
  border: 1px solid #888;
}
Select maze<pre id=S></pre>
<table cellspacing=5><tr>
<td valign=top><input type=radio name=R onclick='Go(M1)'><br>
<pre id=M1>3,3 to 3,2  
OOOOO
OO.OO
O...O
OOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M2)'><br>
<pre id=M2>15,12 to 16,8
OOOOOOOOOOOOOOOOO
O........O.....OO
O...O..........OO
O.........O....OO
O.O............OO
OO.......O.....OO
O.............OOO
O......O.......~O
O..O...........~O
O.............OOO
O.......O......OO
O.....O...O....OO
O..............OO
OOOOOOOOOOOOOO~~O
OOOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M3)'><br>
<pre id=M3>2,2 to 14,3
OOOOOOOOOOOOOOOO
O~~~~~OOOOO~~~~O
O~~O~OOOOOOO~~OO
O...O..........O
O........O.....O
O..............O
OO.............O
O.............OO
O....~....O....O
O..............O
O..............O
OOOOOOOOOOOOOOOO</pre></td>
<td valign=top><input type=radio name=R onclick='Go(M4)'><br>
<pre id=M4>2,2 to 11,11
OOOOOOOOOOOOOOOOOOO
O~~~~~~~OOOOOOOOOOO
O~~~~...OOOOOOOOOOO
OO~O~..OOOOOOOOOOOO
O..OO.............O
O..............O..O
O....O............O
O.O............~..O
O........OOOO.....O
O.......OOOOO.....O
O.......O~~~O.....O
O.......~~~~~.....O
O.......~~~~~.....O
O..........O......O
O..O..~...........O
O...............O.O
O.....O...........O
O.................O
OOOOOOOOOOOOOOOOOOO</pre></td>
</tr></table>

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.