¿Puede Mario ir al final de este mapa?

13

Cree un programa que determine, dada una entrada de la ruta, si Mario puede llegar al final, denotado por E, desde el principio, denotado por S.

Un camino se verá así:

S = E
=====

En una ruta, los diversos símbolos y lo que representan son:

  • =: pared / piso / techo. Mario no puede caminar a través de la pared, y no puede caerse de un piso, ni saltar de un techo (se golpearía la cabeza)
  • (espacio): aire. Mario puede caminar a través de esto, saltarlo y caer a través de él.
  • S: aire, excepto mostrar dónde comienza Mario. Esto siempre aparecerá en la columna más a la izquierda de la entrada, a nivel del suelo.
  • E: aire, excepto mostrar dónde quiere llegar Mario. Esto siempre aparecerá en la columna más a la derecha de la entrada, a nivel del suelo.

La entrada tendrá espacios en cada lugar donde Mario pueda caminar.

Mario solo puede avanzar; en este ejemplo, Mario no puede llegar a la meta

S
===

 ===
   E
====

ni puede él en este

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

Sin embargo, puede alcanzar el espacio indicado por #(que no aparecerá en la entrada), porque puede saltar hasta cuatro celdas de altura; Mario es sobrehumano. Como otro ejemplo de su sobrehumanidad:

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

Mario puede llegar al Ecaer la gran distancia, sobrevivir y caminar con calma E. Tenga en cuenta que no puede alcanzar el #, porque Mario cae directamente hacia abajo.

Mario puede saltar muy alto, pero no muy lejos en comparación.

S   E
== ==
 = =

Mario puede intentar saltar la brecha, pero fallará y caerá directamente. No puede llegar al final.

Mario puede alcanzar la meta en todos estos ejemplos:

 E
 =
 =
 =
S=
==

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

S
=






=  E
====

Este es el código de golf, ¡por lo que gana menos bytes!

TuxCrafting
fuente
2
En el ejemplo de la caída, mencionas que "él no puede alcanzar el #, porque Mario cae directamente". Si estoy viendo esto correctamente, ¿no caería directamente sobre el #? Además, ¿se definen los saltos como un máximo de 4 espacios hacia arriba y un máximo de 1 espacio, verdad?
GuitarPicker
44
@GuitarPicker Pensé que al principio también, pero si miras detenidamente puedes ver que hay otra columna de espacios antes de la columna con el #. En cuanto a la segunda pregunta: no soy OP pero supongo que tienes razón. (eso es lo que asumí en mi solución)
KarlKastor
1
En el tercer ejemplo (que muestra la altura de salto de Mario), Eno aparece en la columna de la derecha porque el nivel del suelo se extiende uno a la derecha desde el resto del mapa.
Taylor Lopez
1
@Joffan:Mario cannot walk through wall , and cannot fall past a floor, or jump past a ceiling
Tito el
1
@Titus Estoy pensando en Mario saltando al aire libre y eligiendo diferentes pisos para aterrizar, ¿puede llegar al más bajo?
Joffan

Respuestas:

11

Slip , 38 27 25 bytes

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

Requiere que la entrada se rellene en un rectángulo de modo que haya espacios en cada celda que Mario necesita atravesar (potencialmente con una línea inicial llena de espacios). Imprime una cadena que representa la ruta válida (que incluye S, Ey todos los =recorridos excepto el último) o nada si no existe una ruta.

Pruébalo aquí.

Explicación

Slip fue la entrada de Sp3000 a nuestro desafío de diseño de lenguaje de coincidencia de patrones 2D. Es un poco como una extensión 2D de expresiones regulares donde puede dar instrucciones al cursor del motor cuando se permite o se requiere que gire a la izquierda o la derecha. También tiene una característica conveniente donde puede evitar que el cursor avance, permitiéndole hacer coincidir una sola posición dos veces seguidas (con diferentes patrones).

El deslizamiento no tiene algo comparable a la búsqueda de expresiones regulares, pero dado que puede moverse sobre cualquier posición varias veces, uno puede probar la condición y luego regresar. Usamos esto para asegurarnos de que solo saltamos cuando estamos en el suelo moviéndonos hacia la loseta del suelo después de cada paso.

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.
Martin Ender
fuente
9

Java 234 230 221 216 208 207 205 179 Bytes

Mira, vencí a C y Python? ¡He logrado la verdadera trascendencia entre los mortales! Bromas aparte, este fue un desafío divertido. La siguiente función toma la entrada como una matriz de cadenas de columnas, cada una con la misma longitud. Si esto va en contra de las reglas, hágamelo saber. Produce 1, lo que significa una ejecución exitosa de Mario y cualquier otro valor que implique una ejecución fallida de Mario.

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;}

Aquí está la lógica más antigua (que es similar a la versión actual) con ejemplos de uso y salida. Además de algunos comentarios que explican la lógica.

/**
 *
 * @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=");

    }

}
Rohan Jhunjhunwala
fuente
Continuemos esta discusión en el chat .
betseg
@KarlKastor, me entendiste, pero el caso de prueba dado es correcto. El problema es que la operación no especificó si habría múltiples formas en que Mario podría ir en cada paso
Rohan Jhunjhunwala
Bueno, supuse que habría porque siempre asumiría la versión más general si no se especifican restricciones adicionales.
KarlKastor
@KarlKastor, sí, tienes razón
Rohan Jhunjhunwala
7

Python, 260 239 222 215 209 206 Bytes,

pruébalo en ideone (con casos de prueba)

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))

llamar como: f([' S=', ' E='])

notas del parche:

Ahora, como algunas de las otras soluciones, supone que la entrada es una serie de cadenas de colores, cada una de las cuales comienza con un ""

Contenedor para formulario de entrada antiguo: g=lambda x:f(map("".join,zip(*([" "*x.index("\n")]+x.split("\n")))))

Además, arreglé un error por el cual Mario podía saltar bloques por encima de él.

versión sin golf con explicaciones:

frecursivamente se llama a sí mismo en todas las direcciones desde las que Mario puede moverse y,x. Regresa Truecuando alcanza el "E"nd, que luego vuelve a través de todas las llamadas de función hasta que gfinalmente regresa 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
KarlKastor
fuente
Si saltar no ayuda, caes al suelo. Añadir un elseantes de la final return?
Titus
5

Caracoles , 41 37 29 bytes

Gracias a feersum por su ayuda para evitar rutas superpuestas y por guardar 4 bytes.

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

Requiere que la entrada se rellene en un rectángulo de manera que haya espacios en cada celda que Mario necesita atravesar (potencialmente con una línea inicial llena de espacios).

Pruébalo en línea!

Explicación

Snails fue la entrada de Feersum a nuestro desafío de diseño de lenguaje de coincidencia de patrones 2D. Al igual que Slip, también es similar a la expresión regular, pero la principal diferencia es que a) esta admite aserciones (lookarounds) yb) aparte de estas aserciones, no es posible atravesar dos veces ninguna celda de la cuadrícula. Eso hace que este problema sea un poco complicado, ya que hay casos en los que Mario necesita caer en un agujero y saltar de nuevo, por ejemplo:

S E
= =
===

Además de estas diferencias, la sintaxis de los dos idiomas también difiere bastante.

Para evitar el problema de que no podemos atravesar una celda dos veces, siempre alternamos un paso horizontal con un paso vertical. Sin embargo, esto significa que tenemos que manejar una caída antes de pasar por encima del borde. Por lo tanto, las caídas técnicamente atravesarán baldosas del suelo, pero nos aseguraremos de que solo ocurran al lado del espacio abierto.

=\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.
Martin Ender
fuente
4

C, 256 236 213 197 bytes

20 bytes guardados por "Esto siempre aparecerá en la columna más a la izquierda de la entrada"
23 bytes guardados gracias al sistema basado en columnas de @ RohanJhunjhunwala

Pruébalo con ideone, con casos de prueba ...

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;}

Uso:

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

Sin disculpas con la explicación:

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
}
Betseg
fuente
Ideone dice que hay un error de tiempo de ejecución
TuxCrafting
66
Espera, estás codificando en el móvil ಠ_ಠ
TuxCrafting
44
1
(No debe ser malo apostar , solo para garantizar la equidad) @ TùxCräftîñg: ¿Esta solución cumple con su desafío porque toma una serie de cadenas (ya divididas en "\ n") y también tiene como entrada la longitud y el ancho de la mapa (no es parte de la entrada en su desafío)?
KarlKastor
2

PHP, 399 338 284 265 251 bytes

<?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)));

espera entrada como argumento de línea de comando con saltos de línea de estilo Unix y espacios finales en cada línea, devuelve el código de salida 1para el éxito, 0para el fracaso

desglose para funcionar

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
}

pruebas (en función 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>';
Titus
fuente
1
a quien sea: ¿me dejarás saber por qué votaste en contra de esto?
Titus
2

Ruby, 153 147 bytes

Lo siento, Java ... ¡tu lugar como el mejor idioma que no es de golf para el trabajo está siendo tomado!

La entrada es una lista de cadenas de columnas, antepuesta con un solo espacio al estilo de cómo las soluciones Slip y Snails requieren que sus entradas se rellenen con un rectángulo de espacio vacío.

Pruébalo en línea!

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]}}
Tinta de valor
fuente
nooooo .... pero "tomaste prestado" mi método de cadenas de columnas
Rohan Jhunjhunwala
1
Bueno, quiero decir, todos los chicos geniales ya lo estaban haciendo. Podría crear una solución basada en filas más tarde, haciendo una "solución rápida" para modificar las filas en columnas para mantener mi código actual pierde en su Java en 10 bytes, pero una solución real podría ser más corta independientemente
Value Ink
2

Grime, 46 bytes (no competidor)

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

He actualizado Grime varias veces después de publicar este desafío, por lo que esta respuesta no es elegible para ganar. Algunos de los cambios son tan nuevos que no he podido incluirlos en TIO, pero una vez que lo haga, puede probar el programa . En cualquier caso, mi repositorio contiene una versión que maneja este código correctamente.

El programa imprime 1si Mario puede alcanzar la meta, y 0si no. La entrada tiene que contener espacios en todos los lugares que Mario necesita visitar. Para entradas generales, tengo la siguiente solución de 57 bytes :

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

Explicación

La explicación de alto nivel es que el no terminal A, definido en la primera línea, coincide con un sub-rectángulo 1 × 1 de la entrada donde Mario puede alcanzar la meta. Ase define como el literal E(Mario ya está en la meta) o como un patrón 1 × 1 que está en la columna izquierda de un rectángulo 2 × n que contiene un salto válido de Mario a otra coincidencia Aen la columna derecha. La segunda línea cuenta el número de coincidencias Aque también contienen el carácter inicial Sy lo imprime.

Aquí hay un desglose del código:

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.

La idea es que la \ {,-4}parte de la izquierda coincida con el espacio a través del cual Mario salta hacia arriba, y la \ /*parte de la derecha coincide con el espacio en el que luego se cae. Requerimos que aterrice en un partido de A(ya que queremos alcanzar la meta) que está encima de un =. Las pilas verticales debajo de ambas columnas simplemente garantizarán que las columnas tengan la misma altura, por lo que podemos concatenarlas (que es lo que hace el espacio único en el medio). Aquí hay un diagrama de arte ASCII de un ejemplo de salto, dividido en los rectángulos mencionados anteriormente, y con espacios reemplazados por *s:

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

En la segunda línea, la opción n activa el recuento de todas las coincidencias, en lugar de encontrar la primera coincidencia. En la solución general, los espacios también pueden ser caracteres especiales fuera de entrada, y la opción bhace que la entrada se rellene con caracteres fuera de entrada.

¡Espero que todo esto tenga sentido!

Zgarb
fuente