Розв’яжи льодовий лабіринт


19

Крижані лабіринти були однією з моїх улюблених штампів ігор Покемонів з моменту дебюту в Pokémon Gold та Silver. Вашим завданням буде скласти програму, яка вирішує такі типи проблем.

Крижані лабіринти складаються, головним чином, з льоду. Як тільки гравець рухається в напрямку льоду, він продовжуватиме рухатися в тому напрямку, поки не зіткнеться з деякою перешкодою. Є також ґрунт, який можна вільно переміщувати, і він зупинить будь-якого гравця, що рухається по ньому. Остання перешкода - камінь. Стоун не може займати те саме місце, що і гравець, і якщо гравець намагається просунутися в нього, він перестане рухатися раніше, ніж зможе.

Ви отримаєте двовимірний контейнер значень, наприклад список списків або рядок, розділену новими рядками, що містить 3 різних значення для кожного з 3 типів підлоги (Лід, Грунт та Камінь). Ви також отримаєте дві пари (або інші еквівалентні контейнери з двома значеннями), які вказують на координату початку та мети в лабіринті. Вони можуть бути нульовими або індексованими.

Ви повинні вивести список ходів (4 різних значення з біекцією на N, E, S, W), які призвели до того, що гравець прийде до кінця, коли він буде виконаний.

Вхід завжди матиме замкнутий периметр каменю навколо лабіринту, тому вам не доведеться турбуватися про гравця, який виходить з лабіринту

Це тому виграє найменше байтів

Випробування

Тут .буде представляти лід, ~буде представляти грунт, і Oбуде представляти камінь. Координати - 1 індексовано. Кожна літера у розчині представляє напрямок, що починається з цієї літери (наприклад, N= Північ)


Вхідні дані

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

Вихідні дані

N

Вхідні дані

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

Вихідні дані

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

Вхідні дані

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

Вихідні дані

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

Вхідні дані

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

Вихідні дані

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

Чи завжди вхід матиме хоча б одне дійсне рішення?
Павло

@Pavel Ви можете так припустити.
Пшеничний майстер

Чи є тестові приклади (рядок, стовпець) чи (стовпець, рядок)? 1 чи 0 індексовано? Чи вважаються краї дошки стінами?
MildlyMilquetoast


2
@busukxuan Ви можете назавжди потрапити в пастку в лабіринті (див. контрольну скриньку 1)
Пшеничний майстер

Відповіді:


4

Математика, 247 байт

(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]])&

З розривами рядків:

(
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]]
)&

Моя найближча ідея полягала в тому, щоб зобразити положення льоду та ґрунту як вузли у графіку із спрямованими краями, що відповідають легальним рухам, а потім використовувати FindPath. Можна подумати, що визначення правових кроків було б легкою частиною, а пошук рішення було б важкою частиною. Для мене це було навпаки. Відкрийте для пропозицій щодо обчислення ребер.

Перший аргумент #- це 2D масив, де 0представлений лід, 1являє собою грунт і 2являє собою камінь.

Другий аргумент #2і третій аргумент #3є початковою і кінцевою точками відповідно у формі {row,column}.

є 3-байтним символом приватного використання, що U+F4A1представляє \[Function].

Пояснення

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

Визначає функцію, pяка приймає список xформи {row,column}та виводи #[[row,column]]; тобто значення льоду / ґрунту / каменю на цій координаті.

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

Визначає функцію, mяка займає вихідний cвектор положення і напрямок vі рекурсивно визначає, де б ви опинилися. Якщо c+vлід, то ми продовжуємо ковзати з цієї точки, тому він повертається m[c+v,v]. Якщо c+vґрунт, то ми рухаємось до c+vта зупиняємось. Інакше (якщо c+vкамінь або поза межами), ви не рухаєтесь. Зверніть увагу, що це призначено лише для позицій на льоду чи ґрунті.

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

Визначає перелік gльоду та положення ґрунту ( pзначення менше 2).

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

Визначає функцію , aяка приймає стартову позицію cі повертають результати переміщення в {1,0}, {-1,0}, {0,1}та {0,-1}напрямках. Може виникнути певна надмірність. Знову ж таки, це передбачає, що cвідповідає лід чи ґрунт.

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

Визначає список eспрямованих країв, що представляють юридичні кроки. Для кожної позиції #в gобчисліть таблицю ребер #->cдля кожного cз a@#. Тоді, оскільки ми закінчуємо підспіском для кожної позиції #, я вирівнюю перший рівень. Можуть бути кілька петель і кілька ребер.

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

Graph[e]- графік, де вузли - це юридичні положення (лід чи ґрунт), а краї представляють законні ходи (можливо, натикаючись на камінь та не рухаючись). Потім ми використовуємо , FindPathщоб знайти шлях з #2до #3представити у вигляді списку вузлів. Оскільки FindPathможна взяти додаткові аргументи, щоб знайти більше одного шляху, результатом буде фактично список, що містить єдиний шлях, тому я беру перший елемент, використовуючи [[1]]. Потім я беру послідовні Differencesкоординати та Normalizeїх. Таким чином вгору є {-1,0}, вниз є {1,0}, право є, {0,1}а ліве є {0,-1}.

Тестові справи

введіть тут опис зображення

введіть тут опис зображення

введіть тут опис зображення

введіть тут опис зображення

введіть тут опис зображення


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 , як і я, щоб вирішити цю проблему

Введення
Карта лабіринту - це багаторядковий рядок, що використовує Oабо 0для каменю, 8для ґрунту та будь-якої ненульової цифри менше 8 для льоду ( 7добре виглядати).
Початкова та кінцева позиція базуються на нулі.

Вихідні дані
Перелік зміщення, де -1 є W, 1 є E, негативним є менше -1, Nа позитивне перевищує 1S

Менше гольфу

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

Тест

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>

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.