Tu es une souris. Vos amis souris ont tous été capturés et sont inconscients et piégés dans un labyrinthe qui n'a qu'une seule entrée / sortie. Vous avez une carte parfaite du labyrinthe, vous pouvez donc trouver une solution pour vous précipiter et les transporter tous en sécurité. Cependant, le labyrinthe est gardé avec un système de sécurité qui déclenchera une alerte si un seuil de 1000
est atteint, vous faisant être capturé et échouer votre mission de sauvetage.
D'après vos enquêtes précédentes sur le labyrinthe, chaque carré que vous faites (c'est-à-dire chaque mouvement horizontal ou vertical - les souris ne peuvent pas se déplacer en diagonale ) s'ajoute 1
au compteur du système de sécurité. Cependant, si vous portez un poids (soit un bloc de dynamite ou un ami souris inconscient), il ajoute à la place 2
car il détecte la pression supplémentaire. La place d'entrée / sortie n'a pas ce système de sécurité, et ne s'ajoute donc pas au comptoir.
Vous avez un approvisionnement illimité de dynamite que vous avez apporté à l'entrée, vous pouvez donc simplement faire sauter tous les murs pour libérer vos amis. Mais vous devez être prudent avec cela, car chaque explosion ajoute 50
au compteur de la pression concussive. De plus, vous ne pouvez transporter qu'une seule chose à la fois, soit une souris ou un bloc de dynamite. Étant donné que chaque bloc de dynamite ne peut faire exploser qu'un espace de mur, cela signifie que s'il y a plusieurs murs d'affilée, vous devez faire un voyage les mains vides à l'entrée pour en saisir plus.
Exemple élaboré
Supposons que notre labyrinthe ressemble à ceci:
######
#M# E#
######
Je vais utiliser c
pour le comptoir. Nous commençons à l' E
entrée, nous nous déplaçons d'un carré à gauche tout en portant de la dynamite,c=2
. Nous faire exploser la dynamite pour faire exploser le mur, c=52
. Nous déplaçons deux carrés vers la gauche, les mains vides, pour obtenir c=54
, et nous sommes maintenant sur le carré de la souris. Nous ramassons notre ami et replaçons 3 carrés dans le E
xit, mais le dernier carré ne compte pas car il n'a pas de capteurs, il n'y a donc que 2 carrés avec quelque chose sur le dos. Cela signifie que lorsque nous atteignons la sortie avec la souris finale c=58
, ce qui est inférieur à 1000
, et donc la mission réussit.
Défi
Étant donné un labyrinthe d'entrée, affichez si vous, le héros de la souris, pouvez sauver avec succès toutes les souris piégées dans les limites décrites ci-dessus, ou si la mission est un échec.
Contribution
- Un labyrinthe 2D dans n'importe quel format acceptable (chaîne multiligne, tableau de chaînes, etc.).
- Pour ce défi, je vais utiliser
#
à la fois pour les murs intérieurs et extérieurs,M
pour les amis souris, etE
pour l'entrée. - L'entrée ne sera jamais immédiatement adjacente à un mur intérieur (il y aura toujours au moins un espace pour se déplacer librement).
- Vous pouvez remplacer tous les caractères ASCII imprimables que vous souhaitez tant qu'il est cohérent. Cela ne vous permet d'utiliser deux symboles différents pour murs intérieurs contre les murs extérieurs, tant que vous maintenez la cohérence (par exemple, si vous choisissez d'utiliser
@
pour les murs intérieurs à la place, et le congé#
pour l' extérieur, chaque mur intérieur doit être@
et chaque mur extérieur#
). - Le labyrinthe sera toujours entièrement délimité par des murs, mais n'est pas nécessairement rectangulaire. Si vous le souhaitez, vous pouvez supposer que le labyrinthe est rempli d'espaces pour effectuer une entrée rectangulaire (facultatif).
- Le labyrinthe peut avoir des sections inaccessibles sans dynamite.
- Vous ne pouvez pas dynamiter les murs extérieurs du labyrinthe.
Sortie
Un vrai / falsey valeur . Truthy pour "Oui, la souris peut sauver toutes les autres souris" ou Falsey pour "Non, le système d'alarme sera déclenché."
Les règles
- Un programme complet ou une fonction sont acceptables.
- Failles standard sont interdites.
- Il s'agit de code-golf, donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) l'emporte.
Exemples
Exemples véridiques, séparés par des lignes blanches.
#####
#M E#
#####
######
#M# E#
######
########
#E # M#
# # #
# # #
# #
########
#############################
# ## # # #
# M ## M # # #
# ## # M # E #
#M ## # # #
#############################
###############
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMM MM#
#MMMMMMMMMMMME#
###############
Exemples de Falsey, séparés par des lignes vides
#############################
#M ## ## ## #
# M ## M ## ## #
# ## ## M ## E #
#M ## ## ## #
#############################
#############################
########
########
# # #
# M # M#
########
#####
# M #
#####
#####
#####
#####
###################
# # # ## ## # # #
#M#M#M## E ##M#M#M#
# # # ## ## # # #
###################
#######
######
#####
####
# M#
####
###############
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMMM#
#MMMMMMMMMMMME#
###############
la source
Réponses:
Perl,
216215 octetsComprend +2 pour
-0p
Donnez votre avis sur STDIN. Utiliser
%
pour les murs extérieurs,#
pour les murs intérieurs,0
pour les espaces vides,8
pour les souris etr
pour la position de départ. Toutes les planches doivent être rembourrées pour former un rectangle. Vous pouvez transformer et exécuter les exemples comme:dynamite.pl
:Remplace le
\xhh
évasions pour le score réclamé.Le programme ne peut pas gérer de manière réaliste les cas complexes. En particulier, il ne peut gérer aucun des cas de défaillance. En effet, il existe simplement trop de façons différentes de faire sauter les murs internes ou de prendre des souris, de sorte que la recherche devient trop large et utilise trop de mémoire, même si elle est au moins suffisamment intelligente pour ne jamais traiter le même état plusieurs fois. La limite de pression doit être abaissée à
100
environ pour des durées d'exécution et une utilisation de la mémoire quelque peu supportables.Explication
J'utilise le motif binaire d'un caractère pour représenter l'état d'un champ:
Par exemple, le héros (
01000000
) porteur de dynamite (00000001
) doit être sur un endroit où il peut marcher (00010000
) et nous voulons que toutes les valeurs soient imprimables en ASCII (00100000
). Prendre le bit à bitor
de tous ces masques de bits donne01110001
quel est le code ASCII pourq
. Au total, cela devient ::Le programme ne considérera que le héros se déplaçant vers la droite (la rotation expliquée plus tard s'occupera des autres directions). Les bitmasks ont été soigneusement choisis de telle sorte que le héros soit toujours représenté par une lettre et un endroit où il peut se déplacer par un chiffre (sauf le héros à la maison portant une victime, mais là encore, c'est intentionnel pour que le seul mouvement du héros soit de tomber) la victime). Donc, un héros qui peut avancer est égalé par
/\pL\d/
. La sous-chaîne correspondante doit être modifiée afin que le héros et ce qu'il porte soient supprimés du premier personnage et ajoutés au second, ce qui peut être fait avec un bit à bitxor
avec la même valeur pour les deux caractères. La valeur xor se compose du bit de héros (01000000
), du bit de dynamite (00000001
) et du bit de souris de transport (00000100
). Ensemble , ilsor
à01000101
qui est ASCIIE
. Déplacer le héros devient donc:Le héros peut faire exploser un mur s'il se tient juste en face et porte de la dynamite (
q
,s
ouy
). Le héros perdra sa dynamite (xor
avec00000001
) et le mur#
se transformera en un passage0
(xor avec00010011
), doncPour gérer les autres directions, la planche entière est tournée (la planche tournée se termine
$o
):Outre le déplacement, le héros a également un certain nombre d'autres choix qu'il peut faire:
Cela se fait par
Le plateau est terminé si le héros est à la maison sans rien porter (
x
) et qu'il n'y a plus de victime à sauver (non2
). Cela peut être facilement testé en utilisantUne fois le tableau résolu, je veux me souvenir de cet état et à la fin l'imprimer. Pour cela je porte le drapeau "est résolu"
$\
et je l' imprime à la fin du programme sans imprimer$_
, doncLes états à traiter à la pression 0 sont maintenus
@0
, à la pression 1 activée,@1
etc. La pression actuelle est maintenue$%
. L' aide$n
ou quelque chose comme ça serait plus court mais le code ne fonctionne pas si la variable est pas initialisé à quelque chose parce que autovivification va autrement changer$n
à un reference.Looping ARRAY sur les états à une certaine pression est effectuée à l' aide d' unfor
et non pasmap
parce que avec un,for
vous pouvez étendre le tableau pendant qu'il est encore en boucle et récupérer les nouveaux éléments. Cela est nécessaire car les rotations et les choix de champ unique du héros se produisent en 0 temps et se retrouvent dans le même tableau de pression. Donc, la boucle pour une pression donnée se fait parCeci est répété jusqu'à ce que la pression atteigne 1000 ou qu'une solution soit trouvée:
Il ne reste plus qu'à ajouter des états récemment découverts à leurs réseaux de pression respectifs. Cela se fera par sous-programme
f
. Nous voulons seulement ajouter un état s'il n'a pas encore été vu. Les États qui ont été vus auparavant sont conservés%a
:$n
représente la nouvelle pression pour un état. Je tirerai cela de l'état que les variables d'expression régulière ont encore à la suite de l'action du héros menant à cet appel:Cela conduit à la formule suivante pour
$n
:Toutes les substitutions obtiennent un
r
modificateur afin qu'elles retournent l'état modifié et laissent l'état actuel$_
seul.f
est ensuite appelé sur cet état modifié, vous obtenez donc du code commeParce que le calcul des
$n
besoins des variables regex, ils doivent par défaut être désactivés au cas où les substitutions ne changeraient rien (car la condition pour les déclencher n'est pas remplie). Je ne dois pas non plus récupérer de variables regex dans une boucle précédente. Par conséquent, les substitutions sont enveloppées dans des{}
blocs pour enregistrer et restaurer l'état regex. Voilà comment vous obtenez des déclarations commeEn particulier, la rotation est tellement enveloppée qu'elle appelle
f
sans variables d'expression régulière et obtient une contribution de pression de 0.Il ne reste plus qu'à amorcer
@0
avec l'état initial au départC'est dans la boucle principale, donc il essaie également d'ajouter
$_
aux tableaux de pression ultérieurs, mais puisque l'état initial sera déjà dans%a
rien, il ne se passera rien.Ensemble, tout cela trouve fondamentalement la solution la plus courte en utilisant l'algorithme de Dijkstra . Il y a cependant un problème potentiel. Le code actuel n'ajoutera pas d'état s'il est redécouvert avec une pression inférieure à la première découverte. Je n'ai pas été en mesure de construire un tableau qui déclencherait cela, mais je n'ai pas non plus été en mesure de prouver que c'est impossible.
la source
JavaScript,
863834785781 octets29 octets enregistrés grâce à ETHproductions
53 octets enregistrés grâce à Jordan
Prend l'entrée comme une chaîne multiligne.
Cela définit une fonction anonyme qui utilise une fonction récursive
f
pour déterminer si vous déclenchez l'alarme avant de récupérer toutes les souris.f
renvoie1000
si la pression est supérieure à 1000 (pour éviter une récursion sans fin), renvoie la pression s'il n'y a plus de souris à sauver et la souris à la sortie, et renvoie la pression minimale de tous les mouvements possibles depuis l'état actuel sinon. Il utilise un tableauL
pour garder une trace des positions déjà visitées oùL[pos]==0
s'il est visité et indéfini s'il ne l'est pas. Cela peut ne pas être nécessaire, mais cela empêche la souris de faire des mouvements inutiles et de lancer des erreurs de récursion à tout le moins. (Cela signifie que vous devez redéfinirL
si vous testez cela plusieurs fois)Cela utilise le format de la question autre que celui qui vous oblige à utiliser un caractère différent pour les murs extérieurs. (Tout autre chose que
# MEmecd
)Version plus lisible:
la source
s in L|p > 999
.eval
et en le remplaçant@
par$1
(vous ne savez pas si cela fonctionnera, mais vous écrivez$1
beaucoup)f
un one-liner:f=(...)=>s in L|p>999?1e3:!/M/.test(s,L[s]=0)&/E/.test(s)?p:Math.min(...
$1
18 fois et.replace("@","$1")
fait 18 octets. Je ne vois pas de moyen de le retirer.