Remplissez le labyrinthe avec un serpent qui suit le mur jusqu'à ce qu'il se coince

21

Faites remplir un labyrinthe par un serpent (jusqu'à ce qu'il se coince).

Le serpent

Le serpent commence à un point de départ donné, pointant vers l' Est . Il se déplace en ayant toujours un mur ou une partie de son corps immédiatement à GAUCHE de sa tête (" suiveur de mur de règle de gauche "), jusqu'à ce qu'il se coince parce que les quatre directions autour de sa tête sont occupées. (Remarque: un serpent coincé ne peut peut-être pas remplir tout l'espace accessible, mais ce n'est pas le but!)

Le défi

Écrivez un programme ou une fonction qui accepte un labyrinthe en entrée sous la forme d'un texte 2D:

  • L'entrée peut être dans n'importe quel format raisonnable: par exemple une liste de chaînes, une seule chaîne avec des retours à la ligne, un fichier.
  • Le labyrinthe a des murs (" #"), des espaces vides (" ") et exactement un point de départ (" o").
  • Vous pouvez choisir de

    • soit supposer que la première et la dernière ligne et colonne sont entièrement des murs;
    • ou supposer que chaque entrée est considérée comme ayant une couche extérieure implicite de murs
  • Vous pouvez supposer que le point de départ a un mur (ou un mur implicite) directement au-dessus (NORD) et que le serpent peut effectuer un mouvement de départ valide dans la direction EST ou SUD.

  • Vous pouvez supposer qu'aucun autre caractère n'est présent dans le texte (sauf les retours à la ligne si votre saisie en a besoin).
  • Vous pouvez supposer que toutes les lignes ont la même longueur.

et imprime / retourne un "labyrinthe rempli" en sortie, avec un instantané du serpent au moment où il s'est coincé :

  • Le corps du serpent est représenté par les caractères >v<^pointant vers l'endroit où se trouve son prochain segment
  • Le point de départ du serpent est soit sa direction au départ (" >" à moins qu'il n'ait à tourner immédiatement) soit un opersonnage (pas besoin d'être cohérent)
  • Le point final du serpent est un opersonnage

Notation

Golf de code habituel: le code le plus court gagne

Exemple

in:
#################################
#                    o          #
#                               #
#     ##       ###       ##     #
#    ##     ##     ##     ##    #
#    ##     ##     ##     ##    #
#    ##      ##   ##      ##    #
#   ##       ##   ##       ##   #
#   ##         ###         ##   #
#    ##       #####       ##    #
#    ##       #####       ##    #
#    ##        ###        ##    #
#     ##                 ##     #
#                               #
#                               #
#################################

out:
#################################
#>>>>>>>>>>>>>>>>>>>v>>>>>>>>>>v#
#^>>>>>>>>>>>>>>>>>v>>>>>>>>>>vv#
#^^   ##>>>>>>v###o>>>>>v##   vv#
#^^  ##>^   ##>>>>^##   >v##  vv#
#^^  ##^    ##     ##    v##  vv#
#^^  ##^     ##   ##     v##  vv#
#^^ ##>^     ##   ##     >v## vv#
#^^ ##^<       ###       v<## vv#
#^^  ##^      #####      v##  vv#
#^^  ##^      #####      v##  vv#
#^^  ##^<      ###      v<##  vv#
#^^   ##^<<<<<<<<<<<<<<<<##   vv#
#^^<<<<<<<<<<<<<<<<<<<<<<<<<<<<v#
#^<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<#
#################################

Animé (à des fins d'illustration):

entrez la description de l'image ici

Edit: notez qu'en cas de doute, le serpent doit "garder sa main gauche" sur le mur sur lequel il se trouve, en suivant les coins, sans sauter sur un mur à 1 pâté de maisons.

entrez la description de l'image ici

Merci Jonathan Allan pour l'avoir soulevé, et Draco18s pour l'instantané explicatif ci-dessus.

Autres exemples

in:
####################
#               o# #  
#                ###
#                  #
#      ##          #
#                ###
####################

out:
####################
#>>>>>>>>>>>>>>vv# #
#^>>>>>>>>>>>>vvv###
#^^   v<<<o<<<<v>>v#
#^^<<<<##^<<<<<<v<<#
#^<<<<<<<<<<<<<<<###
####################
in:
####################
#         o    #####  
#              #####
#                  #
#                 ##
####################

out:
####################
#         >>>>v#####
#             v#####
#             >>>>o#
#                 ##
####################
in:
################
#o             #
#   ########## #
# #          # #
# #          # #
# #          # #
# #  #       # #
# #          # #
# #          # #
# #          # #
# ############ #
#              #
################

out:
################
#>>>>>>>>>>>>>v#
#>>v##########v#
#^#>>>>>>>>>v#v#
#^#>>>>>>>>vv#v#
#^#^>>>>>>vvv#v#
#^#^^#    vvv#v#
#^#^^o<<<<<vv#v#
#^#^^<<<<<<<v#v#
#^#^<<<<<<<<<#v#
#^############v#
#^<<<<<<<<<<<<<#
################
Nicola Sap
la source
Dans l'exemple GIF, quand il entre dans le modèle, pourquoi ne reviendrait-il pas pour remplir les autres parties des espaces vides? Il était certainement possible de tourner à gauche puis en haut puis à gauche puis en bas puis en arrière, mais le serpent a choisi tout droit vers le bas. Le but est-il de remplir autant d'espaces que possible avec le serpent ou de suivre uniquement la stratégie "tourner à droite en rencontrant un mur et terminer si tourner à droite deux fois"?
Magic Octopus Urn
2
@MagicOctopusUrn Je ne suis pas sûr de comprendre à quel point vous voyez l'ambiguïté. Mais, pour répondre à votre question, le but n'est pas de remplir autant d'espace que possible. Cependant, l'algorithme ("suiveur de mur") n'est pas seulement "tourner à droite une fois ou, si possible, deux fois": si le serpent se retrouve sans mur à sa gauche, il devra tourner à gauche à la place (en gardant la "gauche"). main "sur le mur / sur lui-même)
Nicola Sap
(désolé, j'ai mal lu votre résumé de l'algorithme)
Nicola Sap
2
@ jonah: correct. Il n'y a qu'un seul chemin déterministe et ce n'est pas optimal. @ encre de valeur: oui. @ jonathanallan J'ai du mal à voir l'ambiguïté mais c'est peut-être juste moi. Ma version de l'algorithme de suivi de mur est la suivante: gardez votre direction à moins que vous n'ayez plus d'obstacle sur votre gauche [évalué en premier], auquel cas tournez à gauche, ou frappez un mur [évalué en deuxième], auquel cas tournez à droite si possible, ou game over.
Nicola Sap
1
J'ai dû disséquer le gif pour comprendre pourquoi l'état final était tel qu'il était. Cela ne ressort pas du cadre final affiché, mais plutôt de l'état juste avant: i.stack.imgur.com/kj67V.png J'espère que cela aide les gens.
Draco18s

Réponses:

8

Fusain , 94 68 octets

F²⊞υSW¬⁼§υ⁰§υ±¹⊞υS≔⪫υ¶θPθ…θ⌕θo≔⁰θW№KV «≧⁺⊖⌕E³§KV⁺θκ θ✳§rdluθ§>v<^θ»o

Essayez-le en ligne! Le lien est vers la version détaillée du code. Explication:

F²⊞υSW¬⁼§υ⁰§υ±¹⊞υS≔⪫υ¶θ

Slurpez l'entrée dans une chaîne. Cela pourrait être évité en utilisant un format d'entrée moins pratique.

Pθ…θ⌕θo

Imprimez l'entrée sans déplacer le curseur, puis imprimez à onouveau de façon à ce que le curseur se retrouve en dessous.

≔⁰θ

Initialisez la direction actuelle.

W№KV «

Répétez pendant qu'il y a encore un espace libre dans une certaine direction.

≧⁺⊖⌕E³§KV⁺θκ θ

Calculez si le serpent peut tourner à gauche ou s'il est obligé de tourner à droite. Le code ≦⊖θW¬⁼§KVθ ≦⊕θfonctionne également pour cela pour le même nombre d'octets, bien qu'il considère 0comme supérieur au lieu de droite, de sorte que le reste du code doit être adapté.

✳§rdluθ§>v<^θ

Sortez le caractère du corps approprié dans la direction appropriée.

»o

Rétablissez la tête. Cela peut également être écrit comme Poqui imprime la tête sans déplacer le curseur à chaque passage à travers la boucle (mais cela permet à la boucle d'être implicitement fermée pour le même nombre d'octets).

Neil
la source
7

Python 2 , 273 253 242 octets

-11 octets grâce à ArBo

g=input()
d=0
t=lambda g,k=1:'\n'.join(map(''.join,zip(*g.split('\n')[::k])[::-k]))
h='o '
while 1:
 l,r=t(g,-1),t(g)
 if h in l:g=l;d-=1
 elif h in g:g=g.replace(h,'>v<^'[d%4]+'o')
 elif h in r:g=r;d+=1
 else:break
exec-d%4*'g=t(g);'
print g

Essayez-le en ligne!

Cela fonctionne en recherchant la chaîne 'o 'et en la remplaçant par '[>v<^]o', si elle est dans le labyrinthe.

La même vérification sera également effectuée sur le labyrinthe tourné, imprimant le labyrinthe rempli lorsque la chaîne n'est plus là.

La fonction t=lambda g,k=1:'\n'.join(map(j,zip(*g.split('\n')[::k])[::-k]))est utilisée pour faire pivoter la grille

Barre
la source
3

Gelée , 72 56 octets

œṣ€⁾o j€ṛị“v<^>”;”oʋ,
UZ$ṛ¡+ƭ€Ɱ3r5¤ç/€ḟ$Ḣß$ṛ¹?
,0ÇZU$ṛ¡/

Essayez-le en ligne!

Un programme complet qui prend l'entrée comme une liste de chaînes et renvoie une liste de chaînes avec le serpent final. Notez que le pied de page sur TIO convertit une seule chaîne séparée par des sauts de ligne en entrée souhaitée et restaure les sauts de ligne à la fin; c'est simplement pour des raisons de commodité.

Solution quelque peu inspirée par la méthode utilisée par la réponse Python 2 de @ Rod , bien que l'implémentation soit très différente.

Nick Kennedy
la source
3

Rubis , 126 118 octets

-8 octets enregistrés en abusant +=au lieu de chercher manuellement à onouveau après l'avoir repositionné.

->s{d=[q=1,1+l=s=~/$/,-1,~l];i=s=~/o/;(s[i]=">v<^"[q];s[i+=d[q]]=?o)while q=[~-q%4,q,-~q%4].find{|e|s[i+d[e]]==' '};s}

Essayez-le en ligne!

Encre de valeur
la source
3

Requête T-SQL 2008, 373 371 366 octets

J'avais une liste de priorités, toujours glissée à gauche, droite, droite. J'ai changé cette priorité pour toujours glisser en arrière, à gauche, à droite, à droite. Le glissement vers l'arrière sera toujours bloqué, donc la priorité est toujours la même sauf la première glissade. En tournant le serpent vers le bas initialement (C = 4), il tente de se faufiler vers le haut lors de la contre-glissade. Ce petit coup m'a sauvé 2 octets. Parce que je n'avais pas besoin d'ajouter 1 à ~ - ~ -c% 4.

J'ai inséré 2 sauts de ligne pour le rendre lisible

DECLARE @ varchar(8000)=
'################
#o             #
#   ########## #
# #          # #
# #          # #
# #          # #
# #  #       # #
# #          # #
# #          # #
# #          # #
# ############ #
#              #
################';

WITH s as(SELECT 0i,4c,@ m 
UNION ALL
SELECT~-i,x,stuff(stuff(m,~-a+x/3*2+(x-3)%2*s,1,'o')
,a,1,char(59+x+~x%2*11*~x))FROM(SELECT
charindex(' ',replicate(stuff(substring(m,~-a,3),2,1,substring(m,a+~s,1))+
substring(m,a-~s,1)+'~',2),-~-~c%4)%5x,*FROM(SELECT*,charindex('o',m)a,charindex('
',M)S FROM S)Q)L
WHERE x>0)SELECT top 1m FROM s
ORDER BY i
OPTION(MAXRECURSION 0)

J'ai dû faire quelques ajustements mineurs pour exécuter cela en ligne, la version publiée s'exécute dans MS-SQL Server Management Studio.

Appuyez sur Ctrl-T avant de l'exécuter dans MS-SQL Server Management Studio, cela affichera le résultat sous forme de texte.

Essayez-le en ligne

t-clausen.dk
la source
2
Je n'ai aucune idée de comment cela fonctionne, mais je peux vérifier que c'est le cas. Travail incroyable!
BradC
@BradC merci pour la confirmation et le compliment. Les solutions SQL ne sont pas très appréciées ces jours-ci.
t-clausen.dk
1

Python 3 , 343 octets

import sys
X=0,1,0,-1
F,*Y=*X,0
L=3
g=[*map(list,sys.stdin.read().split("\n"))]
e=enumerate
r,c=[[r,c]for r,R in e(g)for c,C in e(R)if"o"==C][0]
while 1:
	if" "==g[r+X[L]][c+Y[L]]:F,L=L,~-L%4
	elif" "<g[r+X[F]][c+Y[F]]:
		if" "<g[r-X[L]][c-Y[L]]:g[r][c]="o";break
		L,F=F,-~F%4
	g[r][c]=">v<^"[F];r,c=r+X[F],c+Y[F]
for r in g:print("".join(r))

Essayez-le en ligne!

-11 octets grâce à ArBo
-4 octets grâce à Jonathan Frech

HyperNeutrino
la source
Vous pouvez jouer au golf l'initialisation X, Yet Fà X=0,1,0,-1;F,*Y=*X,0si je ne me trompe pas. En outre, cela import*vous coûte plus d'octets qu'il n'en économise.
ArBo
@ArBo Oh, je pensais que ça sauvait un peu lol. C'est aussi assez intelligent, merci!
HyperNeutrino
Je pense que vous pouvez enregistrer un octet avec *g,=map(...). Et ça sys.stdin.readlines()marche peut-être?
Andras Deak
1
Alternativement, vous pouvez probablement enregistrer quelques octets en supposant une entrée sur une seule ligne et en utilisant input().
Andras Deak
1
if C=="o"~> if"o"==C, if g[r+X[L]][c+Y[L]]==" ", elif g[r+X[F]][c+Y[F]]>" ", En if g[r-X[L]][c-Y[L]]>" "conséquence.
Jonathan Frech
1

05AB1E , 54 52 octets

[S¶¡øí3FDíø})J€»¼D¾èU¼.Δ.¼„o ©å}DÄiXqë®">^<v"¾è'o«.;

E / S à la fois comme une seule chaîne multiligne.

Essayez-le en ligne ou vérifiez tous les cas de test .

Explication:

[                      # Start an infinite loop:
 S                     #  Split the multi-line string into a list of characters
                       #  (which will use the implicit input in the first iteration)
  ¶¡                   #  Then split by newlines
    øí                 #  Rotate the matrix once clockwise
      3F               #  Loop 3 times:
        D              #   Create a copy of the matrix
         íø            #   And rotate this copy once counterclockwise
       })              #  After the loop: wrap all four matrices into a list
 J                     #  Join each inner-most character-list to string-lines again
  €»                   #  And join each inner list of lines by newlines again
    ¼                  #  Increase variable `c` by 1 (variable `c` is 0 by default)
     D¾<è              #  Index the updated variable `c` in a copy of the list of matrices
                       #  (note that indexing wraps around in 05AB1E)
         U             #  Pop and store it in variable `X`
    ¼                  #  Then increase variable `c` again
                     #  Find the first multi-line string in the list which is truthy for:
                     #   Decrease variable `c` by 1 first
        o             #   Push string "o "
           ©           #   Store this string in variable `®` (without popping)
            å          #   Check if the current multi-line string contains this "o "
    }D                 #  Duplicate the result (results in -1 if none were truthy/found)
      Äi               #  If no result was found:
        X              #   Push variable `X`
         q             #   And stop the program, after which this multi-line string of
                       #   variable `X` is output implicitly as result
       ë               #  Else:
         ">^<v"¾è      #   Get the `c`'th character in string ">^<v"
                       #   (note that indexing wraps around in 05AB1E)
                 'o«  '#   Append a trailing "o" to this character
        ®           .; #   And replace the first variable `®` ("o ") in the 
                       #   multi-line string with this
Kevin Cruijssen
la source
0

Pyth , 161 octets

J.zK[Z1Z_1)=Y+tKZVlJFTl@JNIq@@JNT\oA[NT;=N3=TZ#Iq@@J+G@KN+H@YNd=TN=N%tN4.?In@@J+G@KT+H@YTdIn@@J-G@KN-H@YNd XJGX@JGH\oB=NT=T%hT4)) XJGX@JGH@">v<^"TA(+G@KT+H@YT;jJ

Essayez-le en ligne!

Port de la solution Python 3 d' HyperNeutrino . Maintenant que j'en ai terminé, je pense que j'aurais peut-être dû porter la solution Python 2 de Rod à la place, mais j'ai déjà passé beaucoup trop de temps à ce sujet.

randomdude999
la source