马里奥能否转到此地图的末尾


13

创建一个程序,该程序在给定路径输入的情况下确定Mario是否可以E从头开始由表示为S

路径如下所示:

S = E
=====

在路径中,各种符号及其代表的含义是:

  • =:墙壁/地板/天花板。马里奥(Mario)不能穿过墙壁,也不能跌落地板或跳过天花板(他会撞到头)
  • (空间):空气。马里奥(Mario)可以穿过它,跳过去,跌倒它
  • S:空中,但显示马里奥的出发地。这将始终显示在输入的最左列,即地面上。
  • E:空中,除了显示马里奥想去的地方。这将始终显示在输入的最右侧一栏,即地面。

输入将在Mario可以行走的每个地方都有空间。

马里奥只能前进。在这个例子中,马里奥无法达到目标

S
===

 ===
   E
====

他也不能在这个

    E
   ==
== 
  #==
==
   ==
==
S  ==
======

但是,他可以到达所表示的空间#(不会出现在输入中),因为他可以跳到四个单元格高;马里奥是超人。他超人性的另一个例子:

S
=
=
=
=
=
= #
= =
=
=
=
=     E
=======

马里奥可以E通过掉远距离,生存下来并从容地走到那里来到达目的地E。请注意,他无法到达#,因为马里奥(Mario)直线下降。

马里奥能跳真的通过比较高,但也不是很靠前。

S   E
== ==
 = =

马里奥(Mario)可能会尝试弥补差距,但他会失败,直接跌入。他无法到达终点。

在所有这些示例中,Mario都能实现目标:

 E
 =
 =
 =
S=
==

 =
 =   E
S=   =
==   =
 =   =
 =====

S
=






=  E
====

这是代码高尔夫,所以最少的字节数获胜!


2
在下降的示例中,您提到“他无法到达#,因为Mario直线下降。” 如果我正确查看此内容,他会不会掉下去#?另外,是否将跳转定义为最多4个空格,最多1个空格?
GuitarPicker

4
@GuitarPicker我以为也是这样,但是如果您仔细观察,您会发现在带有的列之前还有另一列空格#。关于第二个问题:我不是OP,但我猜你是对的。(这就是我在解决方案中所假设的)
KarlKastor

1
在第三个示例中(展示了Mario的跳跃高度),E它没有出现在最右边的列中,因为地平面从地图的其余部分向右延伸了一个。
泰勒·洛佩兹

1
@Joffan:Mario cannot walk through wall , and cannot fall past a floor, or jump past a ceiling
Titus

1
@Titus我正在考虑Mario跳入晴朗的空气,并可以选择其他不同的楼层着陆-他能到达较低的楼层吗?
乔芬'16

Answers:


11

单据38 27 25字节

S>(`=<<`P{1,5}>`P>`P*)+#E

要求将输入填充到矩形上,以便每个Mario都需要遍历每个单元格中的空格(可能带有充满空格的引线)。打印代表有效路径的字符串(包括SE以及所有=最后经过的路径,最后一个除外);如果不存在路径,则不输出任何内容。

在这里测试。

说明

S3000Sp3000进入 2D模式匹配语言设计挑战的入门。这有点像regex的2D扩展,您可以在允许或要求它向左或向右转弯时向引擎的光标提供指令。它还具有一项方便的功能,可以防止光标前进,使您可以连续两次匹配单个位置(具有不同的样式)。

Slip没有可与正则表达式中的环视相媲美的东西,但是由于您可以多次移动任何位置,因此可以测试条件然后返回。我们使用它来确保只有在地面上时,才在每个步骤后移入地砖中来跳跃。

S           Match the starting position S.
>           Turn right, so that the cursor points south.
(           One or more times... each repetition of this group represents
            one step to the right.
  `=          Match a = to ensure we've ended up on ground level before.
  <<          Turn left twice, so that the cursor points north.
  `P{1,5}     Match 1 to 5 non-punctuation characters (in our case, either space,
              S or E, i.e. a non-ground character). This is the jump.
  >           Turn right, so that the cursor points east.
  `P          Match another non-ground character. This is the step to the right.
  >           Turn right, so that the cursor points south.
  `P*         Match zero or more non-ground characters. This is the fall.
)+
#           Do not advance the cursor before the next match.
E           Match E, ensuring that the previous path ended on the exit.

9

Java 234230221216208207205179字节

看,我击败了C和python?我实现了凡人间的真正超越!除了所有的笑话,这是一个有趣的挑战。以下函数将输入作为具有相同长度的列字符串数组。如果这违反规定,请告诉我。它输出1表示马里奥运行成功,而其他任何值则表示马里奥运行失败。

int m(String[]a){int l=a.length-1,z=a[l].indexOf(69),m=a[0].indexOf(83),i=1,x;a[l]=a[l].replace("E"," ");for(;i<=l;m=x,i++){if(m-(x=a[i].indexOf('='))>3|x<1)return-1;}return m-z;}

这是带有示例用法和输出的较旧的逻辑(与当前版本相似)。加上一些解释逻辑的注释

/**
 *
 * @author Rohans
 */
public class Mario {

    int m(String[] a) {
//declare variables for the finish the location of mario and the length
        int z, l = a.length - 1, m = a[0].indexOf("S");
        //treat the exit as a space
        z = a[l].indexOf("E");
        a[l] = a[l].replaceAll("E", " ");
        //go through the map
        for (int i = 1, x, r = 1; i <= l; i++) {
            //if mario can safely jump to the next platform (it picks the highest one)
            if (((x = a[i].indexOf("=")) != 0 && (x = a[i].indexOf(" =")) == -1) || m - x > 4) {
                return 0;
            }
            //adjust marios y location
            m = x;
        }
        //make sure mario made it to the end of the level
        return m == z ? 1 : 0;
    }

    public static void MarioTest(String... testCase) {
        System.out.println(new Mario().m(testCase) == 1 ? "Mario made it" : "Mario did not make it");
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        MarioTest("   S=", "=====", "     =", "     =", "=   =", "     E=");

    }

}



@KarlKastor,您确实得到了我,但是给定的测试用例是正确的。问题是,操作人员并没有明确说明马里奥赛车的每一步是否会有多种方式
Rohan Jhunjhunwala

好吧,我猜想是有原因的,因为如果没有指定其他约束,我总是会假设更一般的版本。
KarlKastor '16

@KarlKastor yeah ur right
Rohan Jhunjhunwala

7

Python中,260个 239 222 215 209 206个字节,

在ideone上试用(带有测试用例)

f=lambda m,y=-1,x=0:f(m,m[0].find("S"))if y<0else y<len(m[0])-1and x<len(m)and m[x][y]!="="and(m[x][y]=="E"or m[x][y+1]=="="and any(f(m,y-i,x+1)for i in range(5)[:(m[x][y::-1]+"=").find("=")])or f(m,y+1,x))

像这样打电话 f([' S=', ' E='])

补丁说明:

现在,与其他一些解决方案一样,假设输入是一个由字符串组成的数组,每个字符串均以“”开头

旧输入形式的包装器: g=lambda x:f(map("".join,zip(*([" "*x.index("\n")]+x.split("\n")))))

另外,我修复了一个错误,使马里奥可以跳过他上方的方块。

非高尔夫版本,并附有说明:

f马里奥可以从各个方向递归自称y,x。它True到达时返回"E"nd,然后返回所有函数调用,直到g最终返回True

def g(x):
    #create a array of strings which are the rows of the input
    global m
    m=x.split("\n")
    m=[" "*len(m[0])]+m # because Mario can jump over sometimes
    #Mario starts at the S
    return f([i for i,a in enumerate(m) if a[0]=="S"][0],0)

def f(y,x):
    #print y,x
    if y>len(m)-2 or x>=len(m[0]) or y<0: return False #out of bounds
    if m[y][x]=="E":return True #Reached the goal
    if m[y][x]=="=":return False #We got stuck inside a wall
    if m[y+1][x]=="=": #if you have ground under your feet
        for i in range(5): #jump max 4
            if f(y-i,x+1): #go one forward and try to go further from there
                return True
    return f(y+1,x) ##fall down

如果跳跃没有帮助,则您会跌倒。在加入else前的最后return
泰特斯(Titus)

5

蜗牛41 37 29字节

感谢feersum为避免路径重叠和节省4个字节提供了一些帮助。

=\S(^=d=\=u\ ,4(r!\=d.),r),\E

要求将输入填充到矩形上,以便每个Mario都需要遍历每个单元格中的空格(可能带有充满空格的引线)。

在线尝试!

说明

蜗牛是feersum进入 2D模式匹配语言设计挑战的入门。像Slip一样,它也与regex类似,但主要区别在于:a)这个支持断言(环顾四周),b)除了这些断言,不可能两次遍历网格中的任何单元格。这使这个问题有些棘手,因为在某些情况下,Mario需要掉进一个洞然后跳出来,例如:

S E
= =
===

除了这些差异之外,两种语言的语法也相差很多。

为了避免不能两次遍历一个单元格的问题,我们总是将水平步长与垂直步长交替使用。但是,这意味着我们在跨过壁架之前必须先跌倒。因此,从技术上讲,跌落实际上会穿过地砖,但我们将确保它们仅在开放空间旁边发生。

=\S        Ensure that the match starts on an S, without actually matching it.
(          This group matches zero or more steps to the right (with a potential
           vertical step after each one).
  ^=         Match a non-ground cell, stepping right (on the first iteration,
             there is no step yet, so this matches the S).
  d=\=       Ensure that there's a ground tile below, so that the step ends on
             a valid position.
  u\ ,4      Match 0 to 4 spaces going up. This the optional jump.
  (          This group matches zero or more steps down, if a fall is valid here.
    r!\=       Ensure that there is no ground-tile right of the current cell.
    d.         Take one step down onto any character.
  ),
  r          Reset the direction to right for the next iteration.
),
\E        Match the exit.

4

C,256个 236 213 197字节

@RohanJhunjhunwala的基于列的系统,通过“这将始终出现在输入的最左列”保存的20个字节被节省了
23个字节

使用测试用例在ideone上尝试...

k,y,x,h;f(v,l)char**v;{h=strlen(*v);x=strcspn(*v,"S");while(y<l&x<h)if(v[y][x]==69)return 0;else if(v[y][x+1]^61)x++;else{if(v[y+1][x]==61)while(k<4)if(v[y+1][x-++k]^61){x-=k;break;}y++;}return 1;}

用法:

$ ./mario "S=" " =" " =" " =" "E="
main(c,v)char**v;{printf("%s",f(v+1,c-1)==0?"true":"false");}

不带解释:

k,y,x,h; //omitting int for saving 4 bytes, global variables initialize as 0 by default
f(v,l)char**v;{ //saving 2 bytes
    h=strlen(v[0]); //get height of map
    x=strcspn(v[0],"S"); //where is start point?
    while(y<l&&x<h) //while not out of bounds
        if(v[y][x]==69)return 0; //if we hit end return 0 (69 is ASCII E)
        else if(v[y][x+1]!=61)x++; //we fall one block if there isn't floor underneath us (61 is ASCII =)
        else{
            if(v[y+1][x]==61) //if there is a wall in front of us
                while(k<4) //start counting
                    if(v[y+1][x-++k]!=61){ //if found a way
                        x-=k; //go to there
                        break; //we don't want to jump multiple times
                    }
            y++; //finally, walk one block forwards
        }
    return 1; //if out of bounds
}

Ideone说存在运行时错误
TuxCrafting

6
等待,你是编码在移动ಠ_ಠ
TuxCrafting

4
是的,我将可乐洒在笔记本电脑上:P
betseg

1
(不要刻薄betseg,只是为了确保公平)@TùxCräftîñg:这是解决方案符合您的挑战,因为它需要一个String数组(已分拆的“\ n”),也有作为输入的长度和宽度地图(不是您挑战中输入的一部分)?
KarlKastor '16


2

PHP,399个 338 284 265 251字节

<?function w($m,$p){$w=strpos($m,"
")+1;if($p>strlen($m)|($p%$w)>$w-2|$p<0|'='==$m[$p])return 0;if('E'==$m[$p])die(1);if('='!=$m[$p+$w])return w($m,$p+$w);else for(;$z<5&'='!=$m[$q=$p-$w*$z];$z++)if(w($m,$q+1))die(1);}die(w($m=$argv[1],strpos($m,S)));

期望将输入作为具有unix样式换行符的命令行参数,并在每行中尾随空格,返回1成功的退出代码,0失败的返回代码

功能分解

function w($m,$p) // function walk
{
    $w=strpos($m,"\n")+1;
    if($p<0|$p>strlen($m)|($p%$w)>$w-2  // too high / too low / too far right
        | '='==$m[$p]                   // or inside a wall
    )return 0;
    if('E'==$m[$p])return 1;            // Exit found
    if('='!=$m[$p+$w])return w($m,$p+$w); // no wall below: fall down
    else for($z=0;$z<5                  // else: jump
        & '='!=$m[$q=$p-$w*$z]          // do not jump through walls
        ;$z++)
        if(w($m,$q+1))                  // try to walk on from there
            return 1;
    // no success, return failure (NULL)
}
function m($i){$argv=[__FILE__,$i];
    return w($m=$argv[1],strpos($m,S));     // walk through map starting at position of S
}

测试(在功能m上)

$cases=[
    // examples
    "S = E\n=====",0,
    "S   \n=== \n    \n ===\n   E\n====",0,
    "    E \n   == \n==    \n   == \n==    \n   == \n==    \nS  == \n======",0,
    "S      \n=      \n=      \n=      \n=      \n=      \n=      \n= =    \n=      \n=      \n=      \n=     E\n=======",1,
    "S   E\n== ==\n = = ",0,
    " E\n =\n =\n =\nS=\n==",1,
    "      \n =    \n =   E\nS=   =\n==   =\n =   =\n =====",1,
    "S   \n=   \n    \n    \n    \n    \n    \n    \n=  E\n====",1,
    // additional cases
    "S \n= \n=E",1,
    " == \n == \n    \nS==E\n==  ",1
];
echo'<table border=1><tr><th>input</th><th>output</th><th>expected</th><th>ok?</th></tr>';
while($cases)
{
    $m=array_shift($cases);
    $e=array_shift($cases);
    $y=m($m);
    $w=strpos($m,"\n");
    echo"<tr><td><div style=background-color:yellow;width:",$w*8,"px><pre>$m</pre></div>width=$w</td>
        <td>$y</td><td>$e</td><td>",$e-$y?'N':'Y',"</td></tr>";
}
echo'</table>';

1
给任何人:请您让我知道您为什么对此表示反对?
泰特斯(Titus)

2

红宝石,153个 147字节

抱歉,Java ...您被当做最佳非高尔夫lang的职位已被接管!

输入是列字符串的列表,前面以空格分隔,风格类似于Slip和Snails解决方案要求其输入用空白空格填充的矩形。

在线尝试!

f=->m,j=0,s=p{c,n=m[j,2]
s||=c=~/S/
e=c=~/E/
s+=1 while(k=c[s+1])&&k!=?=
s==e||(0..4).any?{|i|k&&s>=i&&c[s-i,i]!~/=/&&n&&n[s-i]!=?=&&f[m,j+1,s-i]}}

nooooo ....但是您确实“借用”了我的柱状琴弦的方法
Rohan Jhunjhunwala

1
好吧,我的意思是,所有很酷的孩子已经在做这件事了。以后可能会制定一个基于行的解决方案,做一个“速战速决”修改行转换成列,以保持我当前的代码由10个字节失去对Java,但实际的解决方案可能是短不管
价值油墨

2

Grime,46个字节(非竞争)

A=\E|[S ]&<\ {,-4}/0/./* \ /*/A/\=/./*>
n`\S&A

发布此挑战后,我已经多次更新了Grime,因此此答案不符合要求。有些更改太新了,以至于我无法将它们纳入TIO,但是一旦完成,您就可以试用该程序了。无论如何,我的存储库都包含正确处理此代码的版本。

1如果Mario可以达到目标,0则打印程序,否则显示。输入内容必须包含Mario需要访问的所有位置的空间。对于一般输入,我有以下57字节的解决方案:

A=\E|[ \bS]&<[ \b]{,-4}/0/[]/* [ \b]/*/A/\=/[]/*>
nb`\S&A

说明

高层的解释是,A第一行上定义的非终结符与输入的1×1子矩形匹配,马里奥可以达到目标。 A被定义为文字E(Mario已经在目标中),或者被定义为1×1模式,位于某些2×n矩形的左列,其中包含有效的Mario跳转到A右列的另一个匹配项。第二行计算A也包含开始字符的匹配数目S,并打印出来。

这是代码的细分:

A=\E|[ S]&<\ {,-4}/0/./* \ /*/A/\=/./*>
A=                                       Define A as
  \E|                                    a literal E, or
     [ S]&                               a literal space or S
          <                           >  contained in a larger rectangle
                                         that this bracketed expression matches.
           \ {,-4}/0/./*                 Left half of the bracketed expression:
           \ {,-4}                        Rectangle of spaces with height 0-4,
                  /                       below that
                   0                      the 1x1 rectangle we're currently matching,
                    /.                    below that any 1x1 rectangles
                      /*                  stacked any number of times vertically.
                         \ /*/A/\=/./*   Right half of the bracketed expression:
                         \ /*             Spaces stacked vertically,
                             /A           below that another match of A,
                               /\=        below that a literal =,
                                  /./*    below that 1x1 rectangles stacked vertically.

这个想法是,\ {,-4}左边的部分与Mario向上跳跃通过的空间匹配,而\ /*右边的部分与他随后掉落的空间槽匹配。我们要求他进入比赛A(因为我们要达到目标),该比赛位于顶部=。两列下方的垂直堆栈将仅保证这些列具有相同的高度,因此我们可以将它们连接起来(这是中间的单个空格所做的)。这是一个示例跳转的ASCII艺术图,该跳转分为上述矩形,并用*s 替换了空格:

Left column:     Right column:   +---+---+
a = \ {,-4}      d = \ /*        | * | * |
b = 0            e = A           +   +   + d
c = ./*          f = \=          | * | * |
                 g = ./*       a +   +---+
                                 | * | * | e
                                 +   +---+
                                 | * | = | f
                                 +---+---+
                               b | S | = |
                                 +---+   | g
                               c | = | * |
                                 +---+---+

在第二行中,该选项n触发所有匹配项的计数,而不是查找第一个匹配项。在一般解决方案中,空格也可以是特殊的输入失落字符,而option b则用输入失落字符来填充输入。

我希望所有这些都是有道理的!

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.