Gravity Guy peut-il le faire?

27

Gravity Guy est un jeu où la seule entrée utilisateur est une seule touche qui inverse le sens de la gravité. Étant donné un niveau d'art ASCII, déterminez s'il est possible que Gravity Guy atteigne la fin.


Règles

  • La direction de gravité initiale est en baisse .
  • La première colonne de l'entrée ne contiendra toujours qu'une seule # , que Gravity Guy démarre par- dessus.
  • Chaque itération, il se déplace vers le personnage directement à sa droite .
  • Si son chemin est bloqué et qu'il entre dans un #, le joueur perd .
  • Après avoir bougé, le joueur peut éventuellement basculer la gravité de bas en haut ou de haut en bas.
  • Gravity Guy tombe# ensuite sur le suivant (dans le sens de la gravité actuel).
  • S'il n'y a personne #sur qui tomber et qu'il tombe de la grille , le joueur perd .
  • Si Gravity Guy s'écarte du côté droit de la grille d'entrée, le joueur gagne .

Exemple

S'il s'agissait de la grille d'entrée:

  ### 

#  # #
 ###  

Gravity Guy commencerait à xet à ces positions après chaque itération. ^= changer la gravité vers le haut et v= changer la gravité vers le bas.

v                        ^                               v
-------------------------------------------------------------
  ###   |    ###   |    ###   |    ###   |    ###   |    ### 
x       |          |    x     |     x    |      x   |        
#  #    |  #x #    |  #  #    |  #  #    |  #  #    |  #  # x
 ### #  |   ### #  |   ### #  |   ### #  |   ### #  |   ### #

Comme vous pouvez le voir, en changeant la gravité à ces moments, Gravity Guy atteint la fin, donc cette entrée retournerait une valeur vraie.

Caractéristiques

  • La grille d'entrée peut être dans n'importe quel format de "grille" approprié (chaîne multiligne remplie d'espaces, tableau de chaînes de ligne, tableau de tableau de caractères, etc.).
  • S'il est possible pour le joueur de gagner le niveau, affichez une truthyvaleur. Sinon, sortez une falseyvaleur.
  • La largeur et la hauteur de la grille seront 50au maximum des caractères.
  • C'est le , que le code le plus court en octets gagne!

Cas de test

(chaque cas séparé par ----------, toutes les lignes vides doivent également être complétées par des espaces)

Vrai

 #########   ########      ######     ######    
          #  #       #    #      #   #      #   
###    #   # #    #   #  #       #  #        #  
  #    ##  # #    ##  # #     # #  #      ##    
  #    #   # #    #   # #    #     #     #######
  #       #  #       #  #     ###  #          # 
  #    ##    #    ##     #       #  #         # 
  #    #          #              #        #   # 
  #    ####################################   # 
  #                                           # 
  ############################################# 

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

   ############   

######      ######

   ############   

----------

  ###   ###  
     # #     
####  #  ####
    #   #    
     # #     
      #      

----------

    ######  
   #        
 ##         
     #######
###     #   
   #    #   
    #####   


----------

    #####   
   #    #   
 ##     #   
     #######
###         
   #        
    ######  

----------

  ### 

#  # #
 ###  

----------

  ###  ###

###     ##
   #    # 
    ##### 

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

    ##### ####   
   #     #    #  
  #   # #  ##  # 
             #  #
#####  ####   #  
               # 
     #########   

----------

 ########################### 
 #   #   #   #     #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 

Faux

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

  ###     ###  
     # # #     
####  # #  ####
    #     #    
     #   #     
      # #      
       #       

----------

  ####### 
  #     # 
 ## ##### 

### ######
  #     # 
  ####### 

----------

 ########################### 
 #   #   #   #  #  #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 
user81655
la source
Sommes-nous autorisés à utiliser la grille sous forme de colonnes?
Neil
@Neil Vous voulez dire un tableau transposé / tourné? Je vais dire non, car cela modifie l'entrée. Mais si votre langue a un columntype spécial , ce serait OK à utiliser, je suppose.
user81655
Est-il possible que la #première colonne soit dans la première ligne?
feersum
@feersum Non, vous pouvez supposer que la grille comprendra de l'espace pour que le Gravity Guy puisse "se tenir debout".
user81655
La honte; la transposition augmente mon nombre d'octets de 20%.
Neil

Réponses:

19

Escargots , 15 octets

L'essayer en ligne?

^
\ n\ ,=\#r}+~

0. ^est une option qui nécessite que le motif commence en haut à gauche.

  1. \ ​: espace de correspondance

  2. n: Tournez de 90 degrés dans les deux sens

  3. \ ,​: correspond à l'espace zéro ou plusieurs fois

  4. =\#vérifiez qu'il y a un #devant nous

  5. r: définir la direction vers la droite

  6. }+: répéter toutes les opérations précédentes une ou plusieurs fois

  7. ~ correspondre à une cellule qui est hors des limites de la grille

feersum
la source
Cela donne 0 pour la plupart des cas de test True
Bassdrop Cumberwubwubwub
@Bas Avez-vous rempli les lignes vides avec des espaces?
Martin Ender
@ MartinBüttner J'ai directement copié certaines entrées, ce qui a en effet supprimé certains espaces. Cela fonctionne en effet après l'ajout d'espaces
Bassdrop Cumberwubwubwub
5
Puisque personne ne l'a encore dit: c'est génial!
DLosc
9

Perl, 93 89 81 77 76 75 74 octets

Comprend +2 pour -0p

Exécutez avec le modèle d'entrée (avec toutes les lignes d'espace remplies à la même longueur) sur STDIN:

gravity.pl < gravity.txt

gravity.pl:

#!/usr/bin/perl -0p
/
/;$n=".{@-}";s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es&&redo;$_=m;w

Cette version basée sur un fichier a besoin de la nouvelle ligne finale, ce qui fait vraiment 75 octets. Mais la version basée sur la ligne de commande n'a pas besoin de cette nouvelle ligne supplémentaire, donc cela compte comme 74 octets:

perl -0pe '/
/;$n=".{@-}";s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es&&redo;$_=m;w' < gravity.txt

Explication:

Cela va construire une chaîne avec un wgars de gravité dans chaque position peut atteindre. Donc, pour l'avant-dernier exemple véridique, il construira:

     #########   
    ##### ####   
   #wwwww#wwww#  
  #w  # #w ##ww# 
wwwww wwwwwww#ww#
#####  ####  w#ww
     wwwwwwwwww# 
     #########   

Donc, le gars de la gravité peut le faire si et seulement s'il y en a un wdans la dernière colonne. La chaîne sera construite en remplaçant un espace accessible par wà chaque tour.

Chaque remplacement sera de la forme

s/prefix \K space postfix/ w | $& /e

ce qui exigera que l'espace soit précédé d'un préfixe et suivi d'un suffixe mais ne remplacera que l'espace wsans nécessiter beaucoup de regroupement avancé.

Supposons qu'il $ncontient une expression régulière qui progressera juste assez pour que les côtés gauche et droit soient exactement en dessous l'un de l'autre. Ensuite, les expressions rationnelles pertinentes sont:

/^( $n)*\K $n#/       From the first position drop down as long as you
                      encounter spaces until you encounter a #. 
                      This puts gravity guy on his starting platform

/#$n\K( $n)*\b /      A space immediately below a # and if you (optionally)
                      go down further from there (as as the descent is
                      over spaces) you get to a space that follows a word
                      boundary. The only way to get a word boundary is if 
                      there is a w in front of that space. This selects the
                      position gravity guy ends up on if starting from that
                      w and gravity is up
/w([w ]$n)*\K $n#/    A w followed by a space (or w) and if you go down from
                      there as long as it is over spaces (or w) you finally
                      end up on a space directly above a #. This handles the
                      gravity down case. The test uses "space or w" instead
                      of just space to handle this case:

                       #
                      ww
                      #x  
                       #

                      Position x is currently a space and must be replaced by a
                      w but the gravity up regex has already put a w directly
                      after the w gravity guy takes off from. So for gravity
                      down we must handle w as if it is still a space. This
                      is not needed for gravity up because regex always matches
                      starting at the earliest possible character, so 
                      gravity up matches before gravity down

Avec cela hors de la façon dont le programme est facile:

#!/usr/bin/perl -0p   Slurp all of STDIN into $_, at the end print $_

/\n/                  Match the first newline (needed to measure the row
                      length)
$n=".{@-}"            $n effectively becomes rowlength-1 times ".". This
                      will be the regex that goes one step down a column

s/#$n\K( $n)*\b |(^|w)([w ]$n)*\K $n#/w|$&/es

                     This is the 3 regexes shown above combined. The s 
                     modifier is needed so the . in $n also matches newline

    &&redo           Keep looping as long as w's keep getting added

$_=m;w\n;            Check if the last column contains a w: He made it!
                     The \n; at the end is not written. These 2 bytes sneakily
                     come from the -p option for the ; and the -e option
                     for the \n
Ton Hospel
la source
3

JavaScript (ES6), 174 octets

a=>[...a[0]].map((_,i)=>[...t].map(x=>s[x]<'#'&&g(s.indexOf('#',x),-1)&&g(s.lastIndexOf('#',x),1),s=a.map(s=>s[i]),t=new Set),t=new Set([0]),g=(i,d)=>i<0||t.add(i+d))&&t.size

Prend un tableau horizontal de chaînes et renvoie le nombre de points de sortie. La transposition du tableau me coûte 29 octets. Non golfé:

function gravity(array) {
    var set = new Set;
    set.add(0); // starting point
    for (var i = 0; i < array[0].length; i++) {
        var s = array.map(s => s[i]); // transpose array
        var old = set;
        set = new Set;
        for (var x of old) {
            if (s[x] == '#') continue; // hit wall
            var j = s.indexOf('#', x); // try downward gravity
            if (j >= 0) set.add(j - 1);
            j = s.lastIndexOf('#', x); // try upward gravity
            if (j >= 0) set.add(j + 1);
        }
    }
    return set.size;
}
Neil
la source
3

Pip , 85 68 62 59 + 1 = 60 octets

Utilise l' -rindicateur pour lire toutes les lignes de stdin.

FcZg{YlFxiIc@xQsyPB(Jc@<x@?`# *$`)+1PB(c@>x@?'#)+x-1i:UQy}i

Essayez-le en ligne!

Brève explication

La stratégie est essentiellement une recherche en largeur. Nous transposons l'entrée et la boucle sur les lignes (colonnes), en conservant une liste des positions y que le joueur pourrait atteindre dans cette colonne. La sortie après la dernière colonne est une liste non vide si le joueur peut gagner, ou une liste vide (qui s'imprime comme une simple nouvelle ligne) si le joueur perd.

Explication complète

Intégré variables utilisées dans ce programme: i == 0, l == [], s == " ".

L' -rindicateur met une liste des lignes d'entrée dans g. FcZg{...}zips get boucles sur chaque colonne c. (Unary Z, lorsqu'il est appliqué à une liste d'itérables, agit comme Python zip(*g), transposant proprement un tableau 2D.) Notez que ce csera une liste, pas une chaîne.

À l'intérieur de la boucle de colonne, nous réinitialisons yla liste vide en Ycliquant l. Fxiboucle i. Dans les versions ultérieures, isera une liste des coordonnées y que le joueur a pu atteindre dans la colonne précédente. La première fois, nous voulons commencer par juste 0(coin supérieur gauche). La variable est préinitialisée en un scalaire 0, pas en une liste [0], mais Pip l'itère très bien de toute façon.

Pour chacune des positions valides dans la dernière colonne, Ic@xQsvérifie s'il y a un espace à cette position dans la colonne actuelle. Sinon, le joueur vient de se heurter à un mur et nous essayons la prochaine possibilité. Si c'est le cas, nous voulons trouver les positions auxquelles le joueur tombera dans cette colonne pour chaque direction de gravité, et les ajouter à la liste en yutilisant l' opérateur Push Back.

La gravité monte (à gauche, dans la version transposée):

(Jc@<x@?`# *$`)+1
  c@<x             Slice everything left of x in the column
 J                 Join into a string so we can do a regex search on it
      @?`# *$`     Find index of the last # in this string
(             )+1  The player's index is the space below/to the right of this #

Gravité descendante (à droite, dans la version transposée):

(c@>x@?'#)+x-1
 c@>x              Slice everything right of x in the column
     @?'#          Find index of the first # in this list (no need to join into string)
(        )+x       Translate to index number in entire column
            -1     The player's index is the space above/to the left of this #

Si le joueur tombe de la grille dans une direction particulière, l' @?opération respective ne trouvera pas de #et donnera zéro. Ce n'est pas un index valide et générera des avertissements lors de la prochaine itération - qui, cependant, ne seront pas visibles sans l' -windicateur. Pour nos besoins, ces cas sont essentiellement éliminés de la considération.

Après la boucle interne, i:UQyprend la liste ydes positions que nous avons construites, élimine les doublons et l'assigne à i. (L'élimination des doublons est nécessaire car sinon la liste des bulles exponentiellement.) Nous passons ensuite à la colonne suivante. Lorsque nous avons parcouru toutes les colonnes, s'il y avait un chemin valide, il y iaura une liste non vide de positions (véridique); sinon, ce sera une liste vide (falsey).

DLosc
la source