Gravity Guy può farcela?


27

Gravity Guy è un gioco in cui l'unico input dell'utente è un singolo tasto che inverte la direzione di gravità. Dato un livello di arte ASCII, determinare se è possibile per Gravity Guy raggiungere la fine.


Regole

  • La direzione di gravità iniziale è verso il basso .
  • La prima colonna dell'input conterrà sempre solo una # , che Gravity Guy inizia .
  • Ogni iterazione, si sposta sul personaggio direttamente alla sua destra .
  • Se il suo percorso è bloccato e si sposta in a #, il giocatore perde .
  • Dopo essersi mosso, il giocatore può facoltativamente cambiare gravità da giù a su, o da su a giù.
  • Gravity Guy quindi passa al successivo# (nell'attuale direzione di gravità).
  • Se non c'è niente #su cui cadere e lui cade dalla griglia , il giocatore perde .
  • Se Gravity Guy si sposta dalla parte destra della griglia di input, il giocatore vince .

Esempio

Se questa era la griglia di input:

  ### 

#  # #
 ###  

Gravity Guy avrebbe iniziato a xessere in queste posizioni dopo ogni iterazione. ^= imposta la gravità verso l'alto e v= imposta la gravità verso il basso.

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

Come puoi vedere, cambiando gravità in questi momenti Gravity Guy raggiunge la fine, quindi questo input restituirà un valore veritiero.

specificazioni

  • La griglia di input può essere in qualsiasi formato "griglia" appropriato (stringa multilinea riempita con spazi, matrice di stringhe di linea, matrice di matrice di caratteri, ecc.).
  • Se è possibile per il giocatore vincere il livello, emettere un truthyvalore. In caso contrario, emettere un falseyvalore.
  • La larghezza e l'altezza della griglia saranno 50al massimo caratteri.
  • Questo è , può vincere il codice più breve in byte!

Casi test

(ogni caso separato da ----------, anche le righe vuote devono essere riempite di spazi)

Vero

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

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

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

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

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

----------

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

----------

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


----------

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

----------

  ### 

#  # #
 ###  

----------

  ###  ###

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

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

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

----------

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

falso

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

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

----------

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

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

----------

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

È consentita la griglia in formato colonnare?
Neil,

@Neil Intendi un array trasposto / ruotato? Sto per dire di no, poiché sta alterando l'input. Ma se la tua lingua ha un columntipo speciale , sarebbe OK usare, suppongo.
user81655

È possibile che #nella prima colonna si trovi nella prima riga?
feersum

@feersum No, puoi supporre che la griglia includa lo spazio in cui Gravity Guy può "stare".
user81655

Vergogna; la trasposizione aumenta il mio conteggio dei byte del 20%.
Neil,

Risposte:


19

Lumache , 15 byte

Provalo online?

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

0 ^è un'opzione che richiede che il modello inizi in alto a sinistra.

  1. \ ​: abbina lo spazio

  2. n: Ruotare di 90 gradi in entrambe le direzioni

  3. \ ,​: abbina lo spazio zero o più volte

  4. =\#controlla che ci sia un #davanti a noi

  5. r: imposta la direzione a destra

  6. }+: eseguire tutte le precedenti una o più volte

  7. ~ abbina una cella che è fuori dai limiti della griglia


Questo dà 0 per la maggior parte dei casi di test True
Bassdrop Cumberwubwubwub il

@Bas Hai riempito le linee vuote di spazi?
Martin Ender,

@ MartinBüttner Ho copiato direttamente alcuni degli input, facendo in tal modo rimosso alcuni degli spazi. Funziona davvero dopo aver aggiunto spazi
Bassdrop Cumberwubwubwub il

5
Dal momento che nessuno lo ha ancora detto: è fantastico!
DLosc,

9

Perl, 93 89 81 77 76 75 74 byte

Include +2 per -0p

Esegui con il modello di input (con lo spazio di tutte le linee riempito della stessa lunghezza) su 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

Questa versione basata su file richiede la nuova riga finale, quindi è di 75 byte. Ma la versione basata sulla riga di comando non ha bisogno di quella nuova riga aggiuntiva, quindi conta come 74 byte:

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

Spiegazione:

Questo costruirà una stringa con una wposizione in cui ogni tipo di gravità può raggiungere. Quindi per il penultimo esempio di verità costruirà:

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

Quindi il ragazzo di gravità può farlo se e solo se c'è un wnell'ultima colonna. La stringa verrà costruita sostituendo uno spazio raggiungibile conw ogni round.

Ogni sostituzione sarà nel modulo

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

che richiederà che lo spazio sia preceduto dal prefisso e seguito dal postfisso, ma sostituisca solo lo spazio wsenza aver bisogno di molti raggruppamenti avanzati.

Supponiamo che $ncontenga una regex che progredirà appena che i lati sinistro e destro sono esattamente uno sotto l'altro. Quindi le regex rilevanti sono:

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

Detto questo, il programma è semplice:

#!/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

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

Accetta una matrice orizzontale di stringhe e restituisce il numero di punti di uscita. La trasposizione dell'array mi costa 29 byte. 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;
}

3

Pip , 85 68 62 59 + 1 = 60 byte

Usa la -rbandiera per leggere tutte le righe di stdin.

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

Provalo online!

Breve spiegazione

La strategia è essenzialmente una prima ricerca. Trasponiamo l'input e eseguiamo il loop sopra le linee (colonne), mantenendo un elenco delle posizioni y che il giocatore potrebbe raggiungere in quella colonna. L'output dopo l'ultima colonna è un elenco non vuoto se il giocatore può vincere, o un elenco vuoto (che viene stampato come una nuova riga finale) se il giocatore perde.

Spiegazione completa

Built-in variabili utilizzate in questo programma: i == 0, l == [], s == " ".

Il -rflag mette un elenco delle linee di input in g. FcZg{...}cerniere ge anelli su ogni colonna c. (Unario Z, quando applicato a un elenco di iterabili, agisce come Python zip(*g), trasponendo ordinatamente un array 2D.) Nota che csarà un elenco, non una stringa.

All'interno del ciclo di colonne, ripristiniamo yl'elenco vuoto facendo una Yrichiesta l. Fxisi avvolge i. Nelle iterazioni successive, iverrà visualizzato un elenco delle coordinate y che il giocatore è stato in grado di raggiungere nella colonna precedente. La prima volta, vogliamo iniziare con solo 0(angolo in alto a sinistra). La variabile è preinizializzata in uno scalare 0, non in un elenco [0], ma Pip scorre su di essa in modo corretto in entrambi i modi.

Per ciascuna delle posizioni valide nell'ultima colonna, Ic@xQscontrolla se nella colonna corrente è presente uno spazio in quella posizione. In caso contrario, il giocatore ha appena incontrato un muro e andiamo avanti per provare la possibilità successiva. In tal caso, vogliamo trovare le posizioni in cui il giocatore cadrà in questa colonna per ciascuna direzione di gravità e aggiungerle all'elenco yusando l' operatore Push Back.

Gravità che sale (a sinistra, nella versione trasposta):

(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à che scende (a destra, nella versione trasposta):

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

Se il giocatore cade dalla griglia in una direzione particolare, la rispettiva @?operazione non troverà un #e darà zero. Questo non è un indice valido e genererà alcuni avvisi nella prossima iterazione, che tuttavia non sono visibili senza la -wbandiera. Per i nostri scopi, questi casi sono essenzialmente eliminati dalla considerazione.

Dopo il ciclo interno, i:UQyprende l'elenco ydelle posizioni che abbiamo creato, elimina i duplicati e lo assegna i. (L'eliminazione dei duplicati è necessaria perché altrimenti l'elenco si gonfia in modo esponenziale.) Passiamo quindi alla colonna successiva. Quando avremo attraversato tutte le colonne, se ci fosse un percorso valido, ici sarà un elenco non vuoto di posizioni (verità); in caso contrario, sarà un elenco vuoto (falsey).

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.