Résolvez un labyrinthe de glace


19

Les labyrinthes de glace ont été l'un de mes agrafes préférées des jeux Pokémon depuis leurs débuts dans Pokémon Gold et Silver. Votre tâche sera de créer un programme qui résout ces types de problèmes.

Les labyrinthes de glace sont principalement constitués, comme leur nom l'indique, de glace. Une fois que le joueur se déplace dans une direction sur la glace, il continuera de se déplacer dans cette direction jusqu'à ce qu'il heurte un obstacle. Il y a aussi du sol qui peut être déplacé librement et empêchera tout joueur de le traverser. Le dernier obstacle est la pierre. La pierre ne peut pas occuper le même espace que le joueur et si le joueur tente d'y pénétrer, il cessera de bouger avant de pouvoir.

Vous recevrez un conteneur de valeurs bidimensionnel, comme une liste de listes ou une chaîne séparée par des sauts de ligne, contenant 3 valeurs distinctes pour chacun des 3 types de revêtements de sol (glace, sol et pierre). Vous recevrez également deux paires (ou d'autres conteneurs de deux valeurs équivalentes) qui indiquent une coordonnée de départ et d'objectif dans le labyrinthe. Ceux-ci peuvent être zéro ou un indexé.

Vous devez produire une liste de mouvements (4 valeurs distinctes avec une bijection sur N, E, S, W) qui feraient arriver le joueur à la fin une fois exécuté.

L'entrée aura toujours un périmètre de pierre fermé autour du labyrinthe afin que vous n'ayez pas à vous soucier de la sortie du labyrinthe du joueur

C'est donc le moins d'octets gagne

Cas de test

Ici .représentera la glace, ~représentera le sol et Oreprésentera une pierre. Les coordonnées sont 1 indexées. Chaque lettre de la solution représente la direction commençant par cette lettre (par exemple N= Nord)


Contribution

OOOOO
OO.OO
O...O
OOOOO

Start : 3,3
End   : 3,2

Production

N

Contribution

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

Production

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

Contribution

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

Production

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

Contribution

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

Production

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

L'entrée aura-t-elle toujours au moins une solution valide?
Pavel

@ Pavel Vous pouvez le supposer.
Wheat Wizard

Les cas de test (ligne, colonne) ou (colonne, ligne)? 1 ou 0 indexé? Les bords des planches comptent-ils comme des murs?
MildlyMilquetoast


2
@busukxuan Vous pouvez être piégé en permanence dans le labyrinthe (voir testcase 1)
Wheat Wizard

Réponses:


4

Mathematica, 247 octets

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

Avec des sauts de ligne:

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

Mon idée immédiate était de représenter les positions de la glace et du sol sous forme de nœuds dans un graphique avec des arêtes dirigées correspondant à des mouvements légaux, puis à les utiliser FindPath. On pourrait penser que déterminer les démarches légales serait la partie facile et trouver la solution serait la partie difficile. Pour moi, c'était le contraire. Ouvert aux suggestions sur la façon de calculer les bords.

Le premier argument #est un tableau 2D où 0représente la glace, 1représente le sol et 2représente la pierre.

Le deuxième argument #2et le troisième argument #3sont les points de départ et d'arrivée, respectivement, dans le formulaire {row,column}.

est le caractère à usage privé de 3 octets U+F4A1représentant \[Function].

Explication

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

Définit une fonction pqui prend une liste xdu formulaire {row,column}et des sorties #[[row,column]]; c'est-à-dire la valeur glace / sol / pierre à cette coordonnée.

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

Définit une fonction mqui prend une position de départ cet un vecteur de direction vet détermine récursivement où vous vous retrouveriez. Si c+vc'est de la glace, alors nous continuons à glisser à partir de ce point, donc il revient m[c+v,v]. Si c+vc'est du sol, alors nous allons vers c+vet nous arrêtons. Sinon (si c+vc'est de la pierre ou hors limites), vous ne bougez pas. Notez que cela est uniquement destiné à être appelé sur des positions de glace ou de sol.

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

Définit la liste gdes positions de la glace et du sol ( pvaleur inférieure à 2).

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

Définit une fonction aqui prend une position de départ cet retourne les résultats de se déplacer dans les {1,0}, {-1,0}, {0,1}, et les {0,-1}directions. Il peut y avoir une redondance. Encore une fois, cela suppose que cela ccorrespond à de la glace ou du sol.

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

Définit la liste edes arêtes dirigées représentant les déplacements légaux. Pour chaque position #dans g, calculez la table des arêtes #->cpour chaque centrée a@#. Puis, comme nous allons nous retrouver avec une sous-liste pour chaque position #, j'aplatis le premier niveau. Il peut y avoir des boucles et des bords multiples.

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

Graph[e]est le graphique où les nœuds sont les positions légales (glace ou sol) et les bords représentent des mouvements légaux (pouvant se cogner contre une pierre et ne pas bouger). Nous utilisons ensuite FindPathpour trouver un chemin de #2à #3représenté sous forme de liste de nœuds. Puisque FindPathpeut prendre des arguments supplémentaires pour trouver plus d'un chemin, le résultat sera en fait une liste contenant un seul chemin, donc je prends le premier élément en utilisant [[1]]. Ensuite je prends Differencesles coordonnées successives et Normalizeles. Ainsi est le haut {-1,0}, le bas est {1,0}, la droite est {0,1}et la gauche est {0,-1}.

Cas de test

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici


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

Utiliser un BFS , comme je l'ai fait pour résoudre ce défi connexe

Entrée
La carte du labyrinthe est une chaîne multiligne, utilisant Oou 0pour la pierre, 8pour le sol et tout chiffre différent de zéro inférieur à 8 pour la glace ( 7regardez bien).
Les positions de début et de fin sont basées sur zéro.

Sortie
Une liste de décalage, où -1 est W, 1 est E, négatif inférieur à -1 est Net un positif supérieur à 1 estS

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

Tester

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>

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.