Чи може Маріо перейти до кінця цієї карти


13

Створіть програму, яка визначає, з урахуванням вводу шляху, чи може Маріо досягти кінця, позначеного Eвід початку, позначеного символом S.

Шлях буде виглядати приблизно так:

S = E
=====

На шляху, різні символи та те, що вони представляють:

  • =: стіна / підлога / стеля. Маріо не може пройти крізь стіну і не може провалитися під підлогу, не стрибати повз стелі (він би вдарився головою)
  • (простір): повітря. Маріо може пройти через це, і стрибати через нього, і падати через нього
  • S: повітря, за винятком показу, звідки починається Маріо. Це завжди відображатиметься в самому лівому стовпці вводу, на рівні землі.
  • E: повітря, за винятком показу, куди Маріо хоче потрапити. Це завжди відображатиметься в самому правому стовпці вводу, на рівні землі.

На вході буде пробіл у кожному місці, де Маріо міг ходити.

Маріо може рухатися лише вперед; у цьому прикладі Маріо не може досягти мети

S
===

 ===
   E
====

і він не може в цьому

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

Однак він може досягти простору, позначеного символом #(який не відображатиметься на вході), оскільки він може стрибати до чотирьох комірок у висоту; Маріо - нелюд. Як ще один приклад його надлюдства:

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

Маріо може дістатися до E, падаючи велику відстань, виживши і спокійно йдучи туди E. Зауважте, що він не може досягти #, тому що Маріо падає прямо вниз.

Маріо може стрибати дійсно високо, але не дуже далеко вперед у порівнянні.

S   E
== ==
 = =

Маріо може спробувати перестрибнути пробіл, але він зазнає невдачі і впаде прямо. Він не може досягти кінця.

Маріо може досягти мети на всіх наведених нижче прикладах:

 E
 =
 =
 =
S=
==

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

S
=






=  E
====

Це кодовий гольф, тому виграє найменше байтів!


2
У падаючому прикладі ви згадуєте, що "він не може досягти #, тому що Маріо падає прямо вниз". Якщо я переглядаю це правильно, чи не впаде він прямо вниз #? Також, чи стрибки визначаються як максимум 4 місця вгору і максимум 1 простір?
GuitarPicker

4
@GuitarPicker Я подумав, що спочатку так само, але якщо придивитися, то можна побачити ще один стовпчик пробілів перед стовпцем з #. Щодо другого питання: Я не ОП, але я гадаю, що ви праві. (це я припустив у своєму рішенні)
KarlKastor

1
У третьому прикладі (демонструючи висоту стрибка Маріо), Eвін не відображається у самій правій колонці, оскільки рівень землі поширюється на один праворуч від решти карти.
Тейлор Лопес

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

1
@Titus Я думаю про те, що Маріо стрибнув у чисте повітря та мав вибір різних поверхів, на яких можна приземлитися - чи може він потрапити на нижній?
Йофан

Відповіді:


11

Ковзання , 38 27 25 байт

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

Необхідно ввести вкладку прямокутника таким чином, щоб у кожній комірці були пробіли, які Маріо повинен пройти (можливо, із провідною лінією, повною пробілів). Друкує або рядок, що представляє дійсний шлях (який включає S, Eі всі =пройдені, крім останнього), або нічого, якщо шлях не існує.

Тестуйте це тут.

Пояснення

Slip - це вхід Sp3000 до нашої задачі дизайну, що відповідає мові 2D. Це трохи схоже на 2D-розширення регулярного виразу, де ви можете давати вказівки курсору двигуна, коли це дозволяється або потрібно робити повороти вліво або вправо. Він також має зручну функцію, за допомогою якої ви можете запобігти просуванню курсору, дозволяючи вам порівнювати одну позицію двічі поспіль (з різними візерунками).

Slip не має нічого подібного до lookarounds у регулярному вираженні, але оскільки ви можете переміщатись по будь-якій позиції кілька разів, можна просто перевірити стан, а потім повернутися. Ми використовуємо це для того, щоб стрибати лише тоді, коли на землю рухаємося в плитку після кожного кроку.

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 234 230 221 216 208 207 205 179 байт

Подивіться, я бив 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, ти мене зрозумів, але даний тестовий випадок правильний. Проблема полягає в тому, що ОП не уточнив, чи буде кілька способів, як маріо може йти на кожному кроці
Рохан Джунхунвалала,

Ну, я припускав, що це буде, тому що я завжди вважав би більш загальну версію, якщо додаткові обмеження не будуть вказані.
KarlKastor

@KarlKastor так ур справа
Рохан Jhunjhunwala

7

Пітон, 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?
Тит

5

Равлики , 41 37 29 байт

Завдяки feersum за деяку допомогу в уникненні шляхів, що збігаються, та збереженні 4 байтів.

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

Необхідно ввести вкладку прямокутника таким чином, щоб у кожній комірці були пробіли, які Маріо повинен пройти (можливо, із провідною лінією, повною пробілів).

Спробуйте в Інтернеті!

Пояснення

Равлики були входом в нашу 2D-модель, що відповідає мовному виклику дизайну. Як і Slip, він також схожий на регулярний вираз, але основна відмінність полягає в тому, що: a) це підтримує твердження (lookarounds) і b) окрім цих тверджень, неможливо двічі пройти жодну клітинку в сітці. Це робить цю проблему трохи хитрою, оскільки є випадки, коли Маріо потрібно потрапити в яму і відскочити назад, наприклад:

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 байт

20 байтів, збережених "Це завжди відображатиметься в самому лівому стовпчику введення".
23 байти збережено завдяки системі на основі стовпців @ RohanJhunjhunwala

Спробуйте це на 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
}

Ідеї ​​кажуть, що є помилка виконання
TuxCrafting

6
Зачекайте, ви кодуєте на мобільному ಠ_ಠ
TuxCrafting

4
Так, я розлив кокс на своєму ноутбуці: P
betseg

1
(Не означає бути betseg , аби забезпечити справедливість) @ TùxCräftîñg: Чи відповідає це рішення вашим завданням, оскільки воно займає масив Strings (вже розділений на "\ n"), а також має введення довжини та ширини карта (не частина входу у ваш виклик)?
KarlKastor


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
кому хто: Чи дозволите, будь ласка, повідомте мені про те, чому ви спростували це?
Тит

2

Рубі, 153 147 байт

Вибачте, Ява ... ваше місце як найкращого гольфу, що не займається гольфом, займається роботою!

Введення - це список рядків стовпців, попередньо виділених єдиним пробілом у стилі того, як рішення "Ковзання" та "Равлики" вимагають, щоб їхні вкладені за допомогою прямокутника порожнього простору.

Спробуйте в Інтернеті!

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
Ну я маю на увазі, всі круті діти вже робили це. Можна пізніше створити рішення на основі рядків, зробивши "швидке виправлення", щоб змінити рядки в стовпці, щоб мій поточний код втратив вашій Java на 10 байт, але фактичне рішення може бути коротшим незалежно
Value Ink

2

Grime, 46 байт (неконкурентний)

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

Я кілька разів оновлював Grime після опублікування цього виклику, тому ця відповідь не підходить для перемоги. Деякі зміни настільки нові, що я не зміг їх включити в TIO, але, як тільки я це зробити, ви можете спробувати програму . У будь-якому випадку, моє сховище містить версію, яка правильно обробляє цей код.

Програма друкує, 1чи може Маріо досягти мети, а 0якщо ні. Вхід повинен містити пробіли в усіх місцях, які Маріо потрібно відвідати. Для загальних входів у мене є таке 57-байтове рішення:

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

Пояснення

Пояснення на високому рівні полягає в тому, що нетермінал A, визначений у першому рядку, відповідає підпрямокутнику 1 × 1 входу, де Маріо може досягти мети. Aвизначається як буквальний E(Маріо вже в цілі), або як візерунок 1 × 1, який знаходиться в лівій колонці якогось 2 × n прямокутника, що містить дійсний перехід Маріо до іншого матчу 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}частина ліворуч відповідає простору, через який Маріо стрибає вгору, а \ /*частина праворуч відповідає космічному жолобу, на який він потім падає вниз. Ми вимагаємо, щоб він приземлився на матч 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запускає підрахунок усіх матчів, а не пошук першого. У загальному рішенні пробіли можуть бути також спеціальними символами, що не вводяться, і опція bпризводить до того, що введення буде зафіксовано символами, які не вводяться.

Я сподіваюся, що все це має сенс!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.