重力家伙能做到吗?


27

Gravity Guy是一款游戏,其中唯一的用户输入就是一个可以翻转重力方向的按键。给定ASCII艺术水平,确定Gravity Guy是否有可能达到终点。


规则

  • 重力的初始方向朝下
  • 输入的第一列将始终仅包含一个 #,其中Gravity Guy 顶部开始
  • 每次迭代,他都直接移到右边的角色。
  • 如果他的路径被挡住并进入a #,玩家输了
  • 移动后,玩家可以选择将重力从向下切换到向上,或从向上切换到向下。
  • 然后,“重力家伙” 跌落到下一个#(在当前重力方向上)。
  • 如果没有#落脚的机会并且他从网格上摔下来,玩家输了
  • 如果Gravity Guy 从输入网格的右侧移开,则玩家将获胜

如果这是输入网格:

  ### 

#  # #
 ###  

x每次迭代后,Gravity Guy将从这些位置开始于and be。^=将重力调高,并v=将重力调低。

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

如您所见,通过在这些时间切换重力,重力家伙到达终点,因此此输入将返回真实值。

技术指标

  • 输入网格可以采用任何适当的“网格”格式(用空格填充多行字符串,行字符串数组,字符数组数组等)。
  • 如果玩家有可能赢得关卡,请输出一个truthy值。如果不是,则输出一个falsey值。
  • 网格的宽度和高度50最多为字符。
  • 这是,请以字节为单位的最短代码获胜!

测试用例

(每种情况均以分隔----------,任何空白行也应填充空格)

真正

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

----------


###

----------

   #####

####    

----------

 #####
 # # #

# # # 
 #####

----------

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

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

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

----------

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

----------

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


----------

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

----------

  ### 

#  # #
 ###  

----------

  ###  ###

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

----------

  #        
     #   # 
       #   
#   #     #
        #  
   #       
      #    
 #         

----------

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

----------

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

 ###
   #
####

----------


### ###

----------

    #   
 ### ###

#### ###
    #   

----------

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

----------

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

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

----------

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

是否允许使用列格式的网格?
尼尔

@Neil您的意思是转置/旋转数组?我要说不,因为它改变了输入。但是,如果您的语言具有特殊column类型,我想可以使用。
user81655 '16

是否有可能在#第一列是第一排?
feersum '16

@feersum没有,你可以假设电网将包括重力盖伊空间中的“立”。
user81655

耻辱; 换位使我的字节数增加了20%。
尼尔

Answers:


19

蜗牛,15字节

在线尝试吗?

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

0。^是一个要求模式从左上方开始的选项。

  1. \ ​:匹配空间

  2. n:向任一方向旋转90度

  3. \ ,​:匹配空间零次或多次

  4. =\#检查#我们前面是否有人

  5. r:将方向设定为正确

  6. }+:执行上述所有一次或多次

  7. ~ 匹配超出网格范围的单元格


对于大多数True测试用例,这将为0
Bassdrop Cumberwubwubwub

@Bas是否用空格填充空白行?
Martin Ender

@MartinBüttner我直接复制了一些输入,确实删除了一些空格。添加空格后它确实可以工作
Bassdrop Cumberwubwubwub 16-4-22

5
既然没有人说:这太棒了!
DLosc '16

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重力家伙可以到达的每个位置的弦。因此,对于倒数第二个真实的示例,它将构建:

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

因此,当且仅当w最后一列中有a时,重力专家才能做到。w每回合将通过替换一个可到达的空间来构造字符串。

每个替换将采用以下形式

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它将是一个列表,而不是字符串。

在列循环中,我们y通过Yanking 重置为空列表lFxi循环结束i。在以后的迭代中,i将是玩家在上一列中可以到达的y坐标的列表。第一次,我们想从0(左上角)开始。变量被预先初始化为Scalar 0,而不是List [0],但是Pip可以通过两种方法进行迭代。

对于最后一列中的每个有效位置,请Ic@xQs检查当前列中该位置是否有空格。如果没有,玩家会碰壁,我们继续尝试下一种可能性。如果是这样,那么我们想在每个重力方向上找到玩家将落入此列的位置,并y使用Push 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)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.