Mario pode ir até o final deste mapa

13

Crie um programa que determine, com base no caminho, se Mario pode chegar ao fim, indicado por E, desde o início, indicado por S.

Um caminho será mais ou menos assim:

S = E
=====

Em um caminho, os vários símbolos e o que eles representam são:

  • =: parede / piso / teto. Mario não pode atravessar a parede e não pode cair no chão ou pular no teto (ele batia na cabeça)
  • (espaço): ar. Mario pode passar por isso, pular e cair
  • S: ar, exceto mostrando onde Mario começa. Isso sempre aparecerá na coluna mais à esquerda da entrada, no nível do solo.
  • E: ar, exceto mostrando onde Mario quer chegar. Isso sempre aparecerá na coluna mais à direita da entrada, no nível do solo.

A entrada terá espaços em todos os lugares onde Mario possa andar.

Mario só pode seguir em frente; neste exemplo, Mario não pode chegar ao objetivo

S
===

 ===
   E
====

nem ele pode neste

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

No entanto, ele pode alcançar o espaço indicado por #(que não aparecerá na entrada), porque ele pode saltar até quatro células de altura; Mario é sobre-humano. Como outro exemplo de sua super-humanidade:

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

Mario pode chegar ao Ecair a grande distância, sobreviver e caminhar com calma E. Note que ele não pode alcançar o #, porque Mario cai diretamente.

Mario pode pular muito alto, mas não muito longe em comparação.

S   E
== ==
 = =

Mario pode tentar pular a brecha, mas ele falhará e cairá direto. Ele não pode chegar ao fim.

Mario pode alcançar a meta em todos esses exemplos:

 E
 =
 =
 =
S=
==

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

S
=






=  E
====

Isso é código de golfe, e o menor número de bytes vence!

TuxCrafting
fonte
2
No exemplo em queda, você menciona que "ele não pode alcançar o #, porque Mario cai diretamente". Se eu estiver vendo isso corretamente, ele não cairá direto no #? Além disso, os saltos são definidos como no máximo 4 espaços acima e no máximo 1 espaço, certo?
GuitarPicker
4
@GuitarPicker Pensei que, a princípio, também, mas se você olhar com atenção, poderá ver que há outra coluna de espaços antes da coluna com o #. Quanto à segunda pergunta: eu não sou OP, mas acho que você está certo. (que é o que eu assumi na minha solução)
KarlKastor
1
No terceiro exemplo (demonstrando a altura do salto de Mario), Enão aparece na coluna mais à direita, porque o nível do solo se estende para a direita do resto do mapa.
Taylor Lopez
1
@Joffan:Mario cannot walk through wall , and cannot fall past a floor, or jump past a ceiling
Titus
1
@Titus Estou pensando em Mario pulando no ar limpo e tendo uma escolha de pisos diferentes para pousar - ele pode chegar ao piso inferior?
Joffan

Respostas:

11

Deslizamento , 38 27 25 bytes

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

Requer que a entrada seja preenchida em um retângulo, de modo que haja espaços em todas as células que Mario precise atravessar (potencialmente com uma linha principal cheia de espaços). Imprime uma string representando o caminho válido (que inclui S, Ee todo o =pisado, exceto a última) ou nada se não existe caminho.

Teste aqui.

Explicação

Slip foi a entrada do Sp3000 nosso desafio de design de linguagem de correspondência de padrões 2D. É um pouco como uma extensão 2D do regex, onde você pode dar instruções ao cursor do mecanismo quando for permitido ou necessário fazer curvas à esquerda ou à direita. Ele também possui um recurso conveniente, onde você pode impedir o avanço do cursor, permitindo combinar uma única posição duas vezes seguidas (com diferentes padrões).

O deslizamento não tem algo comparável às pesquisas em regex, mas como você pode mover-se sobre qualquer posição várias vezes, basta testar a condição e depois retornar. Usamos isso para garantir que só pulemos quando estiver no chão, movendo-nos para o ladrilho do solo após cada etapa.

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
fonte
9

Java 234 230 221 216 208 207 205 179 Bytes

Olha, eu venci C e python? Eu consegui a verdadeira transcendência entre os mortais! Piadas à parte, esse foi um desafio divertido. A função a seguir recebe entrada como uma matriz de cadeias de colunas, cada uma com o mesmo comprimento. Se isso for contra as regras, por favor me avise. Ele gera 1, o que significa uma mario run bem-sucedida e qualquer outro valor que implique uma mario run com falha.

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

Aqui está a lógica mais antiga (que é semelhante à versão atual) com exemplo de uso e saída. Além de alguns comentários explicando a 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
fonte
@KarlKastor, você me pegou, mas o caso de teste fornecido está correto. A questão é que o OP não spefcify se haveria várias maneiras o mario poderia ir em cada etapa
Rohan Jhunjhunwala
Bem, presumi que haveria porque sempre assumiria a versão mais genérica se restrições adicionais não fossem especificadas.
27916 Karl -astor
@KarlKastor yeah ur right
Rohan Jhunjhunwala
7

Python, 260 239 222 215 209 206 Bytes,

experimente em ideone (com casos de teste)

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

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

notas do patch:

Agora, como algumas das outras soluções, assume que a entrada é uma matriz de seqüências de caracteres de cores, cada uma começando com um ""

Wrapper para formulário de entrada antigo: g=lambda x:f(map("".join,zip(*([" "*x.index("\n")]+x.split("\n")))))

Corrigi também um bug em que Mario podia pular através de blocos acima dele.

versão não destruída com explicações:

fchama-se recursivamente em todas as direções para as quais Mario pode se mover y,x. Ele retorna Truequando atinge o "E"nd, que depois volta por todas as chamadas de função até gfinalmente retornar 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
fonte
Se pular não ajuda, você cai no chão. Adicionar um elseantes da final return?
Titus
5

Caracóis , 41 37 29 bytes

Agradecemos ao feersum por alguma ajuda para evitar caminhos sobrepostos e para salvar 4 bytes.

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

Requer que a entrada seja preenchida em um retângulo, de modo que haja espaços em todas as células que Mario precise percorrer (potencialmente com uma linha principal cheia de espaços).

Experimente online!

Explicação

Snails foi a entrada do feersum para o nosso desafio de design de linguagem de correspondência de padrões 2D. Como o Slip, também é semelhante ao regex, mas a principal diferença é que: a) este suporta asserções (lookarounds) eb), além dessas, não é possível atravessar nenhuma célula na grade duas vezes. Isso torna esse problema um pouco complicado, pois há casos em que Mario precisa cair em um buraco e pular de volta, por exemplo:

S E
= =
===

Além dessas diferenças, a sintaxe dos dois idiomas também difere bastante.

Para contornar o problema de que não podemos atravessar uma célula duas vezes, sempre alternamos uma etapa horizontal com uma vertical. No entanto, isso significa que precisamos lidar com uma queda antes de passarmos pela borda. Então, tecnicamente, as quedas passam por ladrilhos no solo, mas garantiremos que elas ocorram apenas ao lado do espaço aberto.

=\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
fonte
4

C, 256 236 213 197 bytes

20 bytes salvos por "Isso sempre aparecerá na coluna mais à esquerda da entrada"
23 bytes salvos graças ao sistema baseado em colunas de @ RohanJhunjhunwala

Experimente em ideone, com casos de teste ...

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

Ungolfed com explicação:

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
fonte
Ideone diz que há um erro de execução
TuxCrafting
6
Espere, você está codificando em dispositivos móveis ಠ_ಠ
TuxCrafting
4
Sim, derramei coca no meu laptop: P
betseg
1
(Não deve ser um objetivo para a betseg , apenas para garantir a equidade) @ TùxCräftîñg: Esta solução é compatível com o seu desafio, pois requer uma série de Strings (já divididas em "\ n") e também tem como entrada o comprimento e a largura do mapa (não faz parte da contribuição do seu desafio)?
22416 Karl -astor
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 da linha de comando com quebras de linha no estilo unix e espaços à direita em cada linha, retorna o código de saída 1 para obter sucesso, 0para falha

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

testes (na função 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
fonte
1
para quem quer que você queira: por favor, deixe-me saber por que você votou contra isso?
Titus
2

Ruby, 153 147 bytes

Desculpe, Java ... seu lugar como o melhor idioma não-golfe para o trabalho está sendo assumido!

Input é uma lista de cadeias de colunas, precedida por um único espaço no estilo de como as soluções Slip and Snails exigem que suas entradas sejam preenchidas com um retângulo de espaço vazio.

Experimente online!

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]}}
Value Ink
fonte
nooooo .... mas u fez "emprestar" o meu método de strings colunar
Rohan Jhunjhunwala
1
Bem, quero dizer, todas as crianças legais já estavam fazendo isso. Pode criar uma solução baseada em linha mais tarde, fazendo uma "solução rápida" para modificar linhas em colunas para manter meu código atual perde a sua Java por 10 bytes, mas uma solução real pode ser mais curto independentemente
Valor de tinta
2

Grime, 46 bytes (não concorrente)

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

Atualizei o Grime várias vezes depois que este desafio foi lançado, portanto, esta resposta não é elegível para ganhar. Algumas das mudanças são tão novas que não consegui inseri-las no TIO, mas, uma vez que você faça isso, você pode experimentar o programa . De qualquer forma, meu repositório contém uma versão que manipula esse código corretamente.

O programa imprime 1se Mario pode alcançar a meta e0 se não. A entrada deve conter espaços em todos os lugares que Mario precisa visitar. Para entradas gerais, tenho a seguinte solução de 57 bytes :

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

Explicação

A explicação de alto nível é que o não-terminal A, definido na primeira linha, corresponde a um sub-retângulo 1 × 1 da entrada, onde Mario pode alcançar a meta. Aé definido como literal E(Mario já está no objetivo) ou como um padrão 1 × 1 que está na coluna esquerda de um retângulo 2 × n contendo um salto válido de Mario para outra partida deA coluna direita. A segunda linha conta o número de correspondências Aque também contém o caractere inicial Se imprime isso.

Aqui está um detalhamento do 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.

A idéia é que a \ {,-4}parte da esquerda corresponda ao espaço pelo qual Mario pula para cima, e a \ /*parte da direita corresponda ao espaço que ele então desce. Exigimos que ele caia em uma partida de A(já que queremos atingir a meta) que está em cima de uma =. As pilhas verticais abaixo de ambas as colunas simplesmente garantirão que as colunas tenham a mesma altura, para que possamos concatená-las (que é o que o espaço único no meio). Aqui está um diagrama de arte ASCII de um exemplo de salto, dividido nos retângulos mencionados acima e com espaços substituídos por *s:

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

Na segunda linha, a opção n aciona a contagem de todas as correspondências, em vez de encontrar a primeira correspondência. Na solução geral, os espaços também podem ser caracteres especiais de saída insuficiente, e a opção bfaz com que a entrada seja preenchida com caracteres fora de entrada.

Espero que tudo isso faça sentido!

Zgarb
fonte