Kann Gravity Guy es schaffen?

27

Gravity Guy ist ein Spiel, bei dem die einzige Benutzereingabe eine einzelne Taste ist, die die Richtung der Schwerkraft umdreht. Bestimmen Sie bei einem vorgegebenen ASCII-Kunstlevel, ob es Gravity Guy möglich ist, das Ende zu erreichen.


Regeln

  • Die anfängliche Richtung der Schwerkraft ist nach unten .
  • Die erste Spalte der Eingabe enthält immer nur eine # , auf der Gravity Guy beginnt .
  • Bei jeder Iteration bewegt er sich zu der Figur rechts von ihm .
  • Wenn sein Weg blockiert ist und er sich in ein bewegt #, verliert der Spieler .
  • Nach dem Bewegen kann der Spieler die Schwerkraft wahlweise von unten nach oben oder von oben nach unten umschalten .
  • Gravity Guy fällt# dann auf den nächsten (in der aktuellen Richtung der Schwerkraft).
  • Wenn es keinen gibt, #auf den man fallen kann und der vom Gitter fällt , verliert der Spieler .
  • Wenn sich Gravity Guy von der rechten Seite des Eingaberasters entfernt, gewinnt der Spieler .

Beispiel

Wenn dies das Eingaberaster war:

  ### 

#  # #
 ###  

Gravity Guy begann xnach jeder Iteration an diesen Positionen. ^= Schwerkraft nach oben und v= Schwerkraft nach unten schalten.

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

Wie Sie sehen, erreicht Gravity Guy durch das Umschalten der Schwerkraft zu diesen Zeiten das Ende, sodass diese Eingabe einen Wahrheitswert zurückgeben würde.

Spezifikationen

  • Das Eingaberaster kann in jedem geeigneten "Raster" -Format vorliegen (mehrzeilige Zeichenfolge, die mit Leerzeichen aufgefüllt ist, eine Reihe von Zeilenfolgen, eine Reihe von Zeichenfolgen usw.).
  • Wenn es dem Spieler möglich ist, das Level zu gewinnen, geben Sie einen truthyWert aus. Wenn nicht, geben Sie einen falseyWert aus.
  • Die Breite und Höhe des Rasters sind 50maximal Zeichen.
  • Das ist , möge der kürzeste Code in Bytes gewinnen!

Testfälle

(durch jeweils getrennte ----------Leerzeilen sollten ebenfalls mit Leerzeichen aufgefüllt werden)

Wahr

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

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

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

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

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

----------

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

----------

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


----------

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

----------

  ### 

#  # #
 ###  

----------

  ###  ###

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

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

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

----------

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

Falsch

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

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

----------

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

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

----------

 ########################### 
 #   #   #   #  #  #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 
user81655
quelle
Dürfen wir das Gitter im Spaltenformat?
Neil
@Neil Du meinst ein transponiertes / gedrehtes Array? Ich werde nein sagen, da es die Eingabe verändert. Aber wenn Ihre Sprache einen speziellen columnTyp hat, wäre das, denke ich, in Ordnung.
user81655
Ist es möglich, dass die #in der ersten Spalte in der ersten Zeile steht?
Feersum
@feersum Nein, Sie können davon ausgehen, dass das Raster Platz für den Gravity Guy bietet, in dem er "stehen" kann.
user81655
Schande; Die Transposition erhöht meine Byteanzahl um 20%.
Neil

Antworten:

19

Schnecken , 15 Bytes

Online ausprobieren?

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

0. ^Bei dieser Option muss das Muster oben links beginnen.

  1. \ ​: Spielraum

  2. n: 90 Grad in beide Richtungen drehen

  3. \ ,​: stimmen null oder mehrmals mit dem Leerzeichen überein

  4. =\#Überprüfen Sie, ob ein #vor uns liegt

  5. r: Richten Sie die Richtung nach rechts

  6. }+: Mindestens einmal alle vorhergehenden Schritte ausführen

  7. ~ stimmen Sie mit einer Zelle überein, die außerhalb der Gittergrenzen liegt

Feersum
quelle
Dies ergibt 0 für die meisten True-Testfälle
Bassdrop Cumberwubwubwub
@Bas Haben Sie die leeren Zeilen mit Leerzeichen aufgefüllt?
Martin Ender
@ MartinBüttner Ich habe einige der Eingaben direkt kopiert und dabei tatsächlich einige der Leerzeichen entfernt. Es funktioniert in der Tat nach dem Hinzufügen von Leerzeichen
Bassdrop Cumberwubwubwub
5
Da hat es noch niemand gesagt: Das ist Awesome!
DLosc
9

Perl, 93 89 81 77 76 75 74 Bytes

Beinhaltet +2 für -0p

Führen Sie mit dem Eingabemuster (mit allen Zeilenabständen auf die gleiche Länge aufgefüllt) auf STDIN aus:

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

Diese dateibasierte Version benötigt den letzten Zeilenumbruch, das sind also wirklich 75 Bytes. Die kommandozeilenbasierte Version benötigt diese zusätzliche Zeile jedoch nicht, sodass dies 74 Bytes sind:

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

Erläuterung:

Dadurch wird eine Saite konstruiert, die von einem wSchwerkraftmann in jeder Position erreicht werden kann. Für das vorletzte wahrheitsgemäße Beispiel wird also konstruiert:

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

So kann es der Schwerkraftmensch genau dann schaffen, wenn es win der letzten Spalte einen gibt. Die Zeichenfolge wird erstellt, indem win jeder Runde ein erreichbarer Bereich durch ersetzt wird .

Jede Ersetzung hat die Form

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

Dies werfordert, dass dem Leerzeichen ein Präfix und anschließend ein Postfix vorangestellt wird, ersetzt jedoch nur das Leerzeichen, ohne dass viele erweiterte Gruppierungen erforderlich sind.

Angenommen, es $ngibt einen regulären Ausdruck, der gerade so weit fortgeschritten ist, dass die linke und die rechte Seite genau untereinander liegen. Dann sind die relevanten regulären Ausdrücke:

/^( $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

Damit ist das Programm einfach:

#!/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
Tonne Hospel
quelle
3

JavaScript (ES6), 174 Byte

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

Nimmt ein horizontales Array von Zeichenfolgen und gibt die Anzahl der Austrittspunkte zurück. Das Vertauschen des Arrays kostet mich 29 Bytes. Ungolfed:

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
quelle
3

Pip , 85 68 62 59 + 1 = 60 Bytes

Verwendet das -rFlag, um alle Zeilen von stdin zu lesen.

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

Probieren Sie es online!

Kurze Erklärung

Die Strategie ist im Wesentlichen eine Breitensuche. Wir transponieren die Eingabe und durchlaufen die Zeilen (Spalten) mit einer Liste der y-Positionen, die der Spieler in dieser Spalte erreichen könnte. Die Ausgabe nach der letzten Spalte ist eine nicht leere Liste, wenn der Spieler gewinnen kann, oder eine leere Liste (die nur als abschließende Zeile gedruckt wird), wenn der Spieler verliert.

Vollständige Erklärung

Integrierte Variablen in diesem Programm verwendet: i == 0, l == [], s == " ".

Das -r Flag fügt eine Liste der Eingabezeilen ein g. FcZg{...}Reißverschlüsse gund Schleifen über jeder Spalte c. (Unary verhält Zsich auf eine Liste von Iterables angewendet wie Python zip(*g)und transponiert ein 2D-Array sauber.) Beachten Sie, dass cdies eine Liste und keine Zeichenfolge ist.

Innerhalb der Spaltenschleife werden wir von yauf die leere Liste zurückgesetztY Ankreuzen zurück l. FxiSchleifen vorbei i. In späteren Iterationen iwird eine Liste der Y-Koordinaten angezeigt, die der Spieler in der vorherigen Spalte erreichen konnte. Beim ersten Mal wollen wir mit nur 0(obere linke Ecke) beginnen. Die Variable ist für einen Skalar vorinitialisiert 0, nicht für eine Liste [0], aber Pip iteriert in beiden Fällen problemlos darüber .

Ic@xQsÜberprüft für jede der gültigen Positionen in der letzten Spalte, ob an dieser Position in der aktuellen Spalte ein Leerzeichen vorhanden ist. Wenn nicht, ist der Spieler einfach gegen eine Wand gelaufen und wir probieren die nächste Möglichkeit aus. In diesem Fall möchten wir für jede Richtung der Schwerkraft die Positionen ermitteln, auf die der Spieler fällt, und sie ymit dem Operator Push Back zur Liste hinzufügen .

Schwerkraft steigt (links in der transponierten Fassung):

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

Die Schwerkraft sinkt (rechts in der transponierten Fassung):

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

Fällt der Spieler in einer bestimmten Richtung vom Gitter, wird der jeweilige @? Operation kein #und gibt Null. Dies ist kein gültiger Index und generiert in der nächsten Iteration einige Warnungen, die jedoch ohne das -wFlag nicht sichtbar sind . Für unsere Zwecke werden diese Fälle im Wesentlichen außer Betracht gelassen.

Nimmt nach der inneren Schleife i:UQydie Liste yder Positionen, die wir erstellt haben, beseitigt Duplikate und weist sie zu i. (Das Eliminieren von Duplikaten ist notwendig, da sonst die Liste exponentiell aufbläht.) Wir gehen dann zur nächsten Spalte. Wenn wir alle Spalten durchlaufen haben und ein gültiger Pfad vorhanden ist, iwird eine nicht leere Liste von Positionen angezeigt (wahrheitsgemäß). Wenn nicht, wird es eine leere Liste (Falsey) sein.

DLosc
quelle