Gravity Guyはそれを実現できますか?


27

Gravity Guyは、ユーザーの入力が重力の方向を反転させる1つのキーのみであるゲームです。ASCIIアートレベルが与えられたら、Gravity Guyが最後に到達できるかどうかを判断します。


ルール

  • 重力の初期方向は下向きです。
  • 入力の最初の列には常にGravity Guy が開始する1つのみ が含まれます。#
  • 繰り返しごとに、彼右側のキャラクターに直接移動します。
  • 彼のパスがブロックされて彼がに移動するなら#、プレーヤーは負けます。
  • 移動後、プレーヤーは重力を下から上、または上から下にオプションで切り替えることができます
  • Gravity Guyは、次に#(重力の現在の方向に)へ進みます。
  • #上に落ちるものがなく、彼がグリッドから落ちる場合、プレーヤーは負けます。
  • Gravity Guy 入力グリッドの右側から移動すると、プレーヤーが勝ちます。

これが入力グリッドの場合:

  ### 

#  # #
 ###  

Gravity Guyはx、各反復の後、これらの位置から開始します。^=重力を上に、v=重力を下に切り替えます。

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

ご覧のように、これらの時間に重力を切り替えると、Gravity Guyは終わりに達するため、この入力は真実の値を返します。

仕様書

  • 入力グリッドは、適切な「グリッド」形式(スペースが埋め込まれた複数行の文字列、行文字列の配列、文字配列の配列など)になります。
  • プレイヤーがレベルに勝つことができる場合、truthy値を出力します。そうでない場合は、falsey値を出力します。
  • グリッドの幅と高さは50最大で文字になります。
  • これは、バイト単位の最短コードが勝つかもしれません!

テストケース

(で区切られた各ケースに----------は、空白行にもスペースを埋め込む必要があります)

本当

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

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

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

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

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

----------

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

----------

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


----------

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

----------

  ### 

#  # #
 ###  

----------

  ###  ###

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

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

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

----------

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

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

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

----------

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

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

----------

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

列形式のグリッドを許可していますか?
ニール

@Neil転置/回転配列を意味しますか?入力を変更するので、ノーと言います。しかし、あなたの言語が特別なcolumnタイプを持っているなら、それは私が推測するのに使用しても大丈夫でしょう。
user81655

#最初の列の最初の行にあることは可能ですか?
feersum

@feersumいいえ、Gravity Guyが「立つ」ためにグリッドにスペースが含まれると仮定できます。
user81655

恥; 転置によりバイトカウントが20%増加します。
ニール

回答:


19

カタツムリ、15バイト

オンラインでお試しですか?

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

0。^パターンは左上から開始する必要があるオプションです。

  1. \ ​:マッチスペース

  2. n:いずれかの方向に90度回転

  3. \ ,​:スペースに0回以上一致する

  4. =\##私たちの前にあることを確認してください

  5. r:方向を右に設定します

  6. }+:先行するすべてを1回以上行う

  7. ~ グリッドの境界外にあるセルに一致する


これが真のテストケースのほとんどのために0を与える
Bassdrop Cumberwubwubwub

@Bas空の行にスペースを埋めましたか?
マーティンエンダー

@MartinBüttner入力の一部を直接コピーしましたが、実際にコピーすると、スペースの一部が削除されました。これは、スペースを追加した後、実際に動作します
Bassdrop Cumberwubwubwub

5
まだ誰も言っていないので、これは素晴らしい!
DLosc

9

Perl、93 89 81 77 76 75 74バイト

+2を含む -0p

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

このファイルベースのバージョンには最後の改行が必要なので、実際には75バイトです。ただし、コマンドラインベースのバージョンでは、余分な改行は必要ないため、これは74バイトとしてカウントされます。

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

説明:

これは、w重力の人が到達できる各位置にa を持つ文字列を作成します。したがって、最後から2番目の真実の例では、以下を構築します。

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

したがってw、最後の列にが存在する場合にのみ、重力の男はそれを作成できます。文字列はw、各ラウンドで1つの到達可能なスペースを置き換えることによって構築されます。

各置換は次の形式になります

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

スペースの前にプレフィックスを付け、その後にポストフィックスを付けることを要求しwますが、高度なグループ化を必要とせずにスペースのみを置き換えます。

$n左側と右側が正確に互いの下になるように十分に進行する正規表現が含まれていると仮定します。次に、関連する正規表現は次のとおりです。

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

これにより、プログラムは簡単になります。

#!/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バイト

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

文字列の水平配列を受け取り、出口点の数を返します。配列の転置には29バイトかかります。ゴルフをしていない:

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

ピップ85 68 62 59 + 1 = 60バイト

-rフラグを使用して、stdinのすべての行を読み取ります。

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

オンラインでお試しください!

簡単な説明

戦略は基本的に幅優先の検索です。入力を転置し、行(列)をループし、その列でプレーヤーが到達できるy位置のリストを保持します。最後の列の後の出力は、プレーヤーが勝つことができる場合は空でないリスト、またはプレーヤーが負ける場合は空のリスト(末尾の改行として印刷される)です。

完全な説明

内蔵このプログラムで使われる変数:i == 0l == []s == " "

-rフラグへの入力の行のリストを置きますg。各列のFcZg{...}ジップgとループc。(単項Z、イテラブルのリストに適用されると、Pythonのように機能しzip(*g)、2D配列をきれいに転置します。)c文字列ではなくリストになることに注意してください。

列ループ内で、anking yによって空のリストにリセットします。ループします。後の反復では、前の列でプレーヤーが到達できたy座標のリストになります。はじめて、ちょうど(左上隅)から始めたいと思います。変数はList ではなくScalar に事前初期化されますが、Pipはどちらの方法でも問題なく繰り返します。YlFxiii00[0]

最後の列の有効な位置ごとIc@xQsに、現在の列のその位置にスペースがあるかどうかを確認します。そうでない場合、プレーヤーは壁にぶつかっただけで、次の可能性を試します。もしそうなら、プレイヤーは重力の各方向についてこの列で落ちる位置を見つけyPush Back演算子を使用してリストに追加します。

重力が上がる(左、転置バージョン):

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

重力が下がる(右、転置バージョン):

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

プレイヤーが特定の方向にグリッドから落ちた場合、それぞれの@?操作はa #を見つけられず、nilを返します。これは有効なインデックスではないため、次の反復で警告が生成されますが、-wフラグがないと表示されません。私たちの目的のために、これらのケースは本質的に考慮から除外されます。

内側のループの後、構築した位置i:UQyのリストyを取得し、重複を排除し、それをに割り当てiます。(そうでなければリストが指数関数的にふくらむので、重複を排除する必要があります。)次の列に進みます。すべての列をループしたときに、有効なパスが存在iする場合、空でない位置のリスト(真の)になります。そうでない場合、空のリストになります(falsey)。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.