Czy Mario może przejść do końca tej mapy

13

Utwórz program, który określa, na podstawie danych wejściowych ścieżki, czy Mario może dotrzeć do końca, oznaczony Eod początku, oznaczony przez S.

Ścieżka będzie wyglądać mniej więcej tak:

S = E
=====

Na ścieżce różne symbole i ich reprezentacje to:

  • =: ściana / podłoga / sufit. Mario nie może przejść przez ścianę i nie może spaść przez podłogę ani skoczyć przez sufit (uderzyłby się w głowę)
  • (spacja): powietrze. Mario może przez to przejść, przeskoczyć i upaść
  • S: powietrze, z wyjątkiem pokazania, gdzie zaczyna się Mario. Będzie to zawsze pojawiać się w lewej kolumnie na wejściu, na poziomie gruntu.
  • E: powietrze, z wyjątkiem pokazania, gdzie Mario chce się dostać. Będzie to zawsze pojawiać się w prawej kolumnie wejścia, na poziomie gruntu.

Wejście będzie zawierało spacje w każdym miejscu, w którym Mario mógłby chodzić.

Mario może tylko iść do przodu; w tym przykładzie Mario nie może dojść do celu

S
===

 ===
   E
====

w tym też nie może

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

Może jednak dotrzeć do miejsca oznaczonego przez #(które nie pojawi się na wejściu), ponieważ może skoczyć do czterech komórek wysoko; Mario jest nadludzki. Jako kolejny przykład jego nadludzkości:

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

Mario może dojść do tego E, spadając z dużej odległości, przeżywając i spacerując spokojnie E. Zauważ, że nie może dosięgnąć #, ponieważ Mario upada prosto.

Mario potrafi skakać naprawdę wysoko, ale w porównaniu z tym niezbyt daleko.

S   E
== ==
 = =

Mario może spróbować przeskoczyć lukę, ale mu się nie uda i wpadnie prosto. Nie może dojść do końca.

Mario może osiągnąć cel we wszystkich tych przykładach:

 E
 =
 =
 =
S=
==

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

S
=






=  E
====

To jest kod golfowy, więc wygrywa najmniej bajtów!

TuxCrafting
źródło
2
W poniższym przykładzie wspominasz, że „nie może dosięgnąć #, ponieważ Mario upada prosto”. Jeśli dobrze to widzę, czy nie spadłby prosto na #? Czy skoki są zdefiniowane jako maksymalnie 4 spacje w górę i maksymalnie 1 spacja, prawda?
GuitarPicker,
4
@GuitarPicker Myślałem, że na początku tak samo, ale jeśli przyjrzysz się uważnie, zobaczysz inną kolumnę spacji przed kolumną z #. Co do drugiego pytania: nie jestem OP, ale zgaduję, że masz rację. (tak założyłem w moim rozwiązaniu)
KarlKastor
1
W trzecim przykładzie (pokazującym wysokość skoku Mario) Enie pojawia się w kolumnie znajdującej się najbardziej na prawo, ponieważ poziom gruntu rozciąga się na prawo od reszty mapy.
Taylor Lopez,
1
@Joffan:Mario cannot walk through wall , and cannot fall past a floor, or jump past a ceiling
Tytus
1
@Titus Myślę o Mario skaczącym w czystym powietrzu i mającym wybór różnych podłóg do lądowania - czy może dostać się na niższy poziom?
Joffan,

Odpowiedzi:

11

Poślizg , 38 27 25 bajtów

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

Wymaga dopełnienia danych wejściowych do prostokąta, tak aby w każdej komórce Mario musiał przejść przez spacje (potencjalnie z wiodącą linią pełną spacji). Drukuje albo ciąg reprezentujący prawidłową ścieżkę (co obejmuje S, Ei wszyscy =chodzić z wyjątkiem ostatniego) lub nic, jeżeli nie istnieje żadna droga.

Sprawdź to tutaj.

Wyjaśnienie

Slip był wejściem Sp3000 do naszego wyzwania projektowania języka w 2D. Przypomina to rozszerzenie 2D wyrażenia regularnego, w którym można podawać instrukcje kursorowi silnika, gdy jest to dozwolone lub wymagane do skrętu w lewo lub w prawo. Posiada również wygodną funkcję, dzięki której można zapobiec przesuwaniu się kursora, umożliwiając dopasowanie jednej pozycji dwa razy z rzędu (z różnymi wzorami).

Poślizg nie ma czegoś porównywalnego do wyrażeń regularnych w wyrażeniu regularnym, ale ponieważ możesz przesuwać dowolną pozycję wiele razy, możesz po prostu przetestować warunek, a następnie powrócić. Używamy tego, aby zapewnić, że skaczemy tylko na ziemi, przechodząc do płytki podłoża po każdym kroku.

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
źródło
9

Java 234 230 221 216 208 207 205 179 bajtów

Słuchaj, pokonałem C i pytona? Osiągnąłem prawdziwą transcendencję wśród śmiertelników! Pomijając wszystkie dowcipy, było to zabawne wyzwanie. Poniższa funkcja przyjmuje dane wejściowe jako tablicę ciągów kolumn o tej samej długości. Jeśli jest to niezgodne z zasadami, daj mi znać. Wyprowadza 1, co oznacza pomyślny przebieg mario, i każdą inną wartość sugerującą nieudany przebieg 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;}

Oto starsza logika (która jest podobna do obecnej wersji) z przykładowym użyciem i danymi wyjściowymi. Plus kilka komentarzy wyjaśniających logikę

/**
 *
 * @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
źródło
@KarlKastor, dostałeś mnie, ale podany przypadek testowy jest poprawny. Problem polega na tym, że operacja nie sprecyzowała, czy mario może iść na wiele sposobów na każdym kroku
Rohan Jhunjhunwala,
Cóż, zakładałem, że tak będzie, ponieważ zawsze zakładałbym bardziej genralną wersję, jeśli nie zostaną określone dodatkowe ograniczenia.
KarlKastor,
@KarlKastor yeah ur right
Rohan Jhunjhunwala
7

Python, 260 239 222 215 209 206 bajtów,

wypróbuj na ideone (z przypadkami testowymi)

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

zadzwoń jak: f([' S=', ' E='])

Opis zmian:

Teraz, podobnie jak niektóre inne rozwiązania, zakłada, że ​​dane wejściowe to tablica ciągów kolorów, z których każde rozpoczyna się od „”

Opakowanie dla starego formularza wejściowego: g=lambda x:f(map("".join,zip(*([" "*x.index("\n")]+x.split("\n")))))

Naprawiłem również błąd, w którym Mario mógł przeskakiwać bloki nad nim.

wersja bez golfa z objaśnieniami:

frekurencyjnie nazywa się we wszystkich kierunkach, z których Mario może się przenieść y,x. Zwraca, Truegdy osiągnie "E"nd, który następnie przechodzi przez wszystkie wywołania funkcji, aż w gkońcu powraca 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
źródło
Jeśli skakanie nie pomoże, upadniesz na ziemię. Dodać elseprzed finałem return?
Titus
5

Ślimaki , 41 37 29 bajtów

Dzięki feersum za pomoc w unikaniu nakładających się ścieżek i zaoszczędzeniu 4 bajtów.

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

Wymaga dopełnienia danych wejściowych do prostokąta, tak aby w każdej komórce Mario musiał przejść przez spacje (potencjalnie z wiodącą linią pełną spacji).

Wypróbuj online!

Wyjaśnienie

Snails było wejściem feersum do naszego wyzwania projektowania języka w dopasowaniu wzorów 2D. Podobnie jak Slip, jest również podobny do wyrażenia regularnego, ale główna różnica polega na tym, że a) ten obsługuje twierdzenia (spojrzenia) ib) oprócz tych zapewnień, nie jest możliwe dwukrotne przejście do żadnej komórki w siatce. To sprawia, że ​​ten problem jest nieco trudny, ponieważ istnieją przypadki, w których Mario musi wpaść do dziury i wyskoczyć z powrotem, np .:

S E
= =
===

Oprócz tych różnic, składnia tych dwóch języków również bardzo się różni.

Aby obejść problem polegający na tym, że nie możemy dwukrotnie przejść przez komórkę, zawsze zmieniamy krok poziomy na pionowy. Oznacza to jednak, że musimy pokonać upadek, zanim przejdziemy przez półkę. Więc technicznie faktycznie spadną przez płytki gruntu, ale upewnimy się, że zdarzają się tylko przy otwartej przestrzeni.

=\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
źródło
4

C, 256 236 213 197 bajtów

20 bajtów zapisanych przez „To zawsze pojawi się w kolumnie po lewej stronie wejścia”
23 bajty zapisane dzięki systemowi opartemu na kolumnie @ RohanJhunjhunwala

Wypróbuj na ideone, z przypadkami testowymi ...

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

Stosowanie:

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

Nieoznakowany z wyjaśnieniem:

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
źródło
Ideone twierdzi, że wystąpił błąd w czasie wykonywania
TuxCrafting
6
Poczekaj, kodujesz na telefonie komórkowym ಠ_ಠ
TuxCrafting
4
Tak, rozlałem colę na laptopa: P
betseg,
1
(Nie należy to oznaczać betseg , tylko w celu zapewnienia uczciwości) @ TùxCräftîñg: Czy to rozwiązanie jest zgodne z twoim wyzwaniem, ponieważ wymaga szeregu ciągów (już podzielonych na „\ n”), a także ma na wejściu długość i szerokość mapa (nie wchodzi w skład Twojego wyzwania)?
KarlKastor
2

PHP, 399 338 284 265 251 bajtów

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

oczekuje danych wejściowych jako argumentu wiersza poleceń z podziałami linii w stylu uniksowym i końcowymi spacjami w każdym wierszu, zwraca kod wyjścia w 1przypadku powodzenia, w 0przypadku niepowodzenia

podział na funkcje

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
}

testy (na funkcji 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>';
Tytus
źródło
1
do kogokolwiek: Czy możesz mi powiedzieć, dlaczego głosowałeś tak?
Tytus
2

Rubin, 153 147 bajtów

Przepraszam, Jawa ... Twoje miejsce jako najlepsze miejsce do gry w golfa zostało przejęte!

Dane wejściowe to lista ciągów kolumn, poprzedzona pojedynczą spacją w stylu, w jaki rozwiązania Slip i Snails wymagają wypełnienia danych wejściowych prostokątem pustej przestrzeni.

Wypróbuj 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]}}
Wartość tuszu
źródło
nooooo .... ale „pożyczyłeś” moją metodę ciągów kolumnowych
Rohan Jhunjhunwala
1
Mam na myśli, że wszystkie fajne dzieciaki już to robiły. Może później opracuję rozwiązanie oparte na wierszach, wykonując „szybką poprawkę” w celu zmodyfikowania wierszy w kolumnach, aby mój bieżący kod stracił na Javie o 10 bajtów, ale rzeczywiste rozwiązanie może być krótsze niezależnie od tego
Value Ink
2

Brud, 46 bajtów (niekonkurencyjny)

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

Kilka razy aktualizowałem Grime po opublikowaniu tego wyzwania, więc ta odpowiedź nie kwalifikuje się do wygrania. Niektóre zmiany są tak nowe, że nie udało mi się wprowadzić ich do TIO, ale kiedy to zrobię, możesz wypróbować program . W każdym razie moje repozytorium zawiera wersję, która poprawnie obsługuje ten kod.

Program drukuje, 1czy Mario może osiągnąć cel, a 0jeśli nie. Dane wejściowe muszą zawierać spacje we wszystkich miejscach, które Mario musi odwiedzić. Do ogólnych danych wejściowych mam następujące 57-bajtowe rozwiązanie:

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

Wyjaśnienie

Wyjaśnienie na wysokim poziomie jest takie, że nieterminalny A, zdefiniowany w pierwszym wierszu, pasuje do pod-prostokąta 1 × 1 wejścia, w którym Mario może osiągnąć cel. Ajest zdefiniowany albo dosłownie E(Mario jest już przy bramce), albo jako wzór 1 × 1 , który znajduje się w lewej kolumnie jakiegoś prostokąta 2 × n i zawiera prawidłowy skok Mario do innego dopasowania Aw prawej kolumnie. Drugi wiersz zawiera liczbę dopasowań, Aktóre zawierają również znak początkowy S, i drukuje je.

Oto podział kodu:

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.

Chodzi o to, że \ {,-4}część po lewej pasuje do przestrzeni, przez którą Mario skacze w górę, a \ /*część po prawej pasuje do koryta przestrzeni, po której następnie spada. Wymagamy, aby wylądował na meczu A(ponieważ chcemy osiągnąć cel), który jest na szczycie =. Pionowe stosy poniżej obu kolumn po prostu zagwarantują, że kolumny będą miały tę samą wysokość, dzięki czemu będziemy mogli je łączyć (co robi pojedyncza przestrzeń na środku). Oto schemat artystyczny ASCII przykładowego skoku, z podziałem na wyżej wspomniane prostokąty i spacje zastąpione przez *s:

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

W drugim wierszu opcja npowoduje zliczanie wszystkich dopasowań, zamiast znajdowania pierwszego dopasowania. W ogólnym rozwiązaniu spacje mogą być również specjalnymi znakami braku danych wejściowych, a opcja bpowoduje, że dane wejściowe są uzupełniane znakami znaków braku danych wejściowych.

Mam nadzieję, że to wszystko ma sens!

Zgarb
źródło