Bisakah Gravity Guy berhasil?

27

Gravity Guy adalah gim di mana satu-satunya input pengguna adalah kunci tunggal yang membalik arah gravitasi. Diberi tingkat seni ASCII, tentukan apakah Gravity Guy mungkin mencapai akhir.


Aturan

  • Arah awal gravitasi sedang turun .
  • Kolom pertama dari input akan selalu hanya berisi satu # , yang dimulai Gravity Guy di atas.
  • Setiap iterasi, ia bergerak ke karakter langsung di sebelah kanannya .
  • Jika jalurnya diblokir dan dia pindah ke #, pemain kalah .
  • Setelah bergerak, pemain dapat secara opsional beralih gravitasi dari bawah ke atas, atau ke atas ke bawah.
  • Gravity Guy kemudian jatuh ke yang berikutnya# (ke arah gravitasi saat ini).
  • Jika tidak ada #jatuh dan dia jatuh dari grid , pemain kalah .
  • Jika Gravity Guy bergerak dari sisi kanan grid input, pemain menang .

Contoh

Jika ini adalah kisi masukan:

  ### 

#  # #
 ###  

Gravity Guy akan mulai di xdan berada di posisi ini setelah setiap iterasi. ^= beralih gravitasi ke atas dan v= beralih gravitasi ke bawah.

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

Seperti yang Anda lihat, dengan beralih gravitasi pada saat ini Gravity Guy mencapai akhir, sehingga input ini akan mengembalikan nilai yang sebenarnya.

Spesifikasi

  • Input grid dapat dalam format "grid" yang sesuai (string multiline yang diisi spasi, array string line, array array karakter, dll).
  • Jika memungkinkan bagi pemain untuk memenangkan level, berikan truthynilai. Jika tidak, keluarkan falseynilai.
  • Lebar dan tinggi kisi akan menjadi 50karakter paling banyak.
  • Ini adalah , semoga kode terpendek dalam byte menang!

Uji Kasus

(setiap case dipisahkan oleh ----------, setiap baris kosong juga harus diisi dengan spasi)

Benar

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

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

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

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

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

----------

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

----------

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


----------

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

----------

  ### 

#  # #
 ###  

----------

  ###  ###

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

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

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

----------

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

Salah

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

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

----------

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

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

----------

 ########################### 
 #   #   #   #  #  #   #   # 
 # # # #   #   # #   #   # # 
 # # # ######### ########### 
 # # # #  #       #     #  # 
   # # # ## ##### ### #      
## #   #    #          ## ###
 # ##### #### ###########  # 
 # #     #  #     #     ## # 
 # # #####  ### # # # # #  # 
 #              #   # #   ## 
 ########################### 
pengguna81655
sumber
Apakah kami mengizinkan kisi dalam format kolom?
Neil
@ Neil Maksudmu array yang dialihkan / diputar? Saya akan mengatakan tidak, karena itu mengubah input. Tetapi jika bahasa Anda memiliki columnjenis khusus , saya rasa tidak masalah untuk menggunakannya.
user81655
Apakah mungkin #kolom di kolom pertama berada di baris pertama?
feersum
@feersum Tidak, Anda dapat mengasumsikan grid akan menyertakan ruang untuk Gravity Guy untuk "berdiri".
user81655
Malu; transposisi meningkatkan jumlah byte saya sebesar 20%.
Neil

Jawaban:

19

Siput , 15 byte

Coba online?

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

0. ^adalah opsi yang memerlukan pola untuk memulai di kiri atas.

  1. \ ​: ruang pertandingan

  2. n: Putar 90 derajat ke kedua arah

  3. \ ,​: ruang pertandingan nol atau lebih banyak kali

  4. =\#periksa apakah ada #di depan kita

  5. r: atur arah ke kanan

  6. }+: lakukan semua yang sebelumnya satu atau lebih kali

  7. ~ cocok dengan sel yang berada di luar batas grid

feersum
sumber
Ini memberikan 0 untuk sebagian besar kasus uji Benar
Bassdrop Cumberwubwubwub
@ Apakah Anda sudah mengisi garis kosong dengan spasi?
Martin Ender
@ MartinBüttner Saya langsung menyalin beberapa input, melakukan hal itu memang menghapus beberapa spasi. Ini memang berfungsi setelah menambahkan spasi
Bassdrop Cumberwubwubwub
5
Karena belum ada yang mengatakannya: Ini Luar Biasa!
DLosc
9

Perl, 93 89 81 77 76 75 74 byte

Termasuk +2 untuk -0p

Jalankan dengan pola input (dengan semua ruang spasi empuk dengan panjang yang sama) di 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

Versi berbasis file ini membutuhkan baris terakhir, jadi itu benar-benar 75 byte. Tetapi versi berbasis baris perintah tidak memerlukan baris baru tambahan sehingga ini dianggap sebagai 74 byte:

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

Penjelasan:

Ini akan membangun string dengan wdi setiap posisi yang bisa dijangkau oleh gravitasi pria. Jadi untuk contoh kebenaran kedua yang terakhir akan dibangun:

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

Jadi pria gravitasi dapat membuatnya jika dan hanya jika ada wdi kolom terakhir. Tali akan dibangun dengan mengganti satu ruang yang dapat dijangkau oleh wdi setiap putaran.

Setiap penggantian harus dalam bentuk

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

yang akan menuntut bahwa ruang didahului dengan awalan dan diikuti oleh postfix tetapi hanya mengganti ruang dengan wtanpa perlu banyak pengelompokan tingkat lanjut.

Asumsikan $nberisi regex yang akan maju cukup sehingga sisi kiri dan kanan persis di bawah satu sama lain. Maka regex yang relevan adalah:

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

Dengan begitu, program ini mudah:

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

Mengambil array horizontal string dan mengembalikan jumlah titik keluar. Transpos array membutuhkan biaya 29 byte. Tidak Disatukan:

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

Pip , 85 68 62 59 + 1 = 60 byte

Menggunakan -rbendera untuk membaca semua baris stdin.

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

Cobalah online!

Penjelasan singkat

Strategi ini pada dasarnya adalah pencarian pertama yang luas. Kami memindahkan input dan loop di atas garis (kolom), menjaga daftar posisi-y yang dapat dijangkau pemain di kolom itu. Output setelah kolom terakhir adalah daftar yang tidak kosong jika pemain bisa menang, atau daftar kosong (yang dicetak hanya sebagai baris baru) jika pemain kalah.

Penjelasan lengkap

Built-in variabel yang digunakan dalam program ini: i == 0, l == [], s == " ".

The -rbendera menempatkan daftar baris masukan ke dalam g. FcZg{...}ritsleting gdan loop di atas setiap kolom c. (Unary Z, ketika diterapkan pada daftar iterables, bertindak seperti Python zip(*g), mentransposisi array 2D dengan rapi.) Perhatikan bahwa itu cakan menjadi daftar, bukan string.

Di dalam loop kolom, kami mengatur ulang yke daftar kosong dengan Ypenjelasan l. Fxiloop lebih i. Dalam iterasi selanjutnya, iakan menjadi daftar koordinat y yang dapat dijangkau pemain di kolom sebelumnya. Pertama kali lewat, kami ingin memulai dengan hanya 0(sudut kiri atas). Variabel diinisialisasi ke Skalar 0, bukan Daftar [0], tetapi Pip iterates baik-baik saja baik cara.

Untuk setiap posisi yang valid di kolom terakhir, Ic@xQsperiksa apakah ada ruang di posisi itu di kolom saat ini. Jika tidak, pemain hanya berlari ke tembok dan kami terus mencoba kemungkinan berikutnya. Jika demikian, maka kami ingin menemukan posisi pemain akan jatuh ke dalam kolom ini untuk setiap arah gravitasi, dan menambahkannya ke daftar ymenggunakan operator PASK Back.

Gravitasi naik (kiri, dalam versi transposisi):

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

Gravitasi turun (kanan, dalam versi transposisi):

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

Jika pemain jatuh dari grid ke arah tertentu, @?operasi masing-masing tidak akan menemukan #dan akan memberikan nol. Ini bukan indeks yang valid dan akan menghasilkan beberapa peringatan di iterasi berikutnya - yang, bagaimanapun, tidak terlihat tanpa -wbendera. Untuk tujuan kami, kasus-kasus ini pada dasarnya dihilangkan dari pertimbangan.

Setelah loop dalam, i:UQyambil daftar yposisi yang telah kami buat, hapus duplikat, dan tetapkan i. (Menghilangkan duplikat diperlukan karena jika tidak, daftar balon secara eksponensial.) Kami kemudian pergi ke kolom berikutnya. Ketika kami telah mengulang semua kolom, jika ada jalur yang valid, iakan ada daftar posisi kosong (benar); jika tidak, itu akan menjadi daftar kosong (falsey).

DLosc
sumber