Bisakah Mario pergi ke ujung peta ini

13

Buat program yang menentukan, diberi input jalur, apakah Mario dapat mencapai akhir, dilambangkan dengan E, dari awal, dilambangkan dengan S.

Path akan terlihat seperti ini:

S = E
=====

Di jalan, berbagai simbol dan apa yang mereka wakili adalah:

  • =: dinding / lantai / langit-langit. Mario tidak bisa berjalan menembus dinding, dan tidak bisa jatuh melewati lantai, atau melompat melewati langit-langit (dia akan mengenai kepalanya)
  • (spasi): udara. Mario bisa berjalan melalui ini, dan melompatinya, dan jatuh melewatinya
  • S: air, kecuali menunjukkan dari mana Mario memulai. Ini akan selalu muncul di kolom paling kiri dari input, di permukaan tanah.
  • E: air, kecuali menunjukkan di mana Mario ingin mendapatkan. Ini akan selalu muncul di kolom input paling kanan, di permukaan tanah.

Masukan akan memiliki ruang di setiap tempat di mana Mario bisa berjalan.

Mario hanya bisa bergerak maju; dalam contoh ini Mario tidak dapat mencapai tujuan

S
===

 ===
   E
====

dia juga tidak bisa dalam hal ini

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

Namun, ia dapat mencapai ruang yang dilambangkan dengan #(yang tidak akan muncul pada input), karena ia dapat melompat hingga empat sel; Mario adalah manusia super. Sebagai contoh lain dari kedewasaannya:

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

Mario dapat mencapai Ejarak yang sangat jauh, bertahan, dan berjalan dengan tenang ke sana E. Perhatikan bahwa ia tidak dapat mencapai #, karena Mario langsung jatuh ke bawah.

Mario dapat melompat sangat tinggi, tetapi tidak terlalu jauh dibandingkan dengan perbandingan.

S   E
== ==
 = =

Mario mungkin mencoba untuk melompati celah, tetapi ia akan gagal, dan langsung jatuh. Ia tidak dapat mencapai akhir.

Mario dapat mencapai tujuan dalam semua contoh ini:

 E
 =
 =
 =
S=
==

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

S
=






=  E
====

Ini adalah kode golf, byte paling sedikit menang!

TuxCrafting
sumber
2
Dalam contoh jatuh, Anda menyebutkan bahwa "dia tidak dapat mencapai #, karena Mario langsung jatuh ke bawah." Jika saya melihat ini dengan benar, bukankah dia akan jatuh langsung ke atas #? Juga, apakah lompatan didefinisikan sebagai maksimum 4 spasi dan maksimum 1 spasi?
GuitarPicker
4
@ GuitarPicker Saya pikir pada awalnya juga tetapi jika Anda melihat dekat Anda dapat melihat ada kolom spasi sebelum kolom dengan #. Mengenai pertanyaan kedua: Saya bukan OP tapi saya kira Anda benar. (itulah yang saya asumsikan dalam solusi saya)
KarlKastor
1
Pada contoh ketiga (menunjukkan ketinggian lompatan Mario), Etidak muncul di kolom paling kanan karena permukaan tanah memanjang satu ke kanan dari sisa peta.
Taylor Lopez
1
@Joffan:Mario cannot walk through wall , and cannot fall past a floor, or jump past a ceiling
Titus
1
@ Titus Saya sedang berpikir tentang Mario melompat ke udara jernih dan memiliki pilihan lantai yang berbeda untuk mendarat - bisakah dia sampai ke lantai bawah?
Joffan

Jawaban:

11

Slip , 38 27 25 byte

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

Membutuhkan input untuk diisi ke persegi panjang sehingga ada ruang di setiap sel yang Mario perlu lintasi (berpotensi dengan garis depan penuh spasi). Mencetak string yang mewakili jalur yang valid (yang mencakup S, Edan semua jalur =berjalan kecuali yang terakhir) atau tidak sama sekali jika tidak ada jalur yang ada.

Uji di sini.

Penjelasan

Slip adalah entri Sp3000 tantangan desain bahasa pencocokan pola 2D kami. Agak seperti perpanjangan 2D regex di mana Anda dapat memberikan instruksi kepada kursor mesin saat diizinkan atau diminta untuk belok kiri atau kanan. Ini juga memiliki fitur yang nyaman di mana Anda dapat mencegah kursor maju, memungkinkan Anda untuk mencocokkan satu posisi dua kali berturut-turut (dengan pola yang berbeda).

Slip tidak memiliki sesuatu yang sebanding dengan lookaround di regex, tetapi karena Anda dapat berpindah posisi apa pun beberapa kali, seseorang hanya dapat menguji kondisinya dan kemudian kembali. Kami menggunakan ini untuk memastikan bahwa kami hanya melompat ketika di tanah dengan pindah ke ubin tanah setelah setiap langkah.

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

Java 234 230 221 216 208 207 205 179 Bytes

Lihat, saya mengalahkan C dan python? Saya telah mencapai transendensi sejati di antara manusia! Selain lelucon, ini adalah tantangan yang menyenangkan. Fungsi berikut mengambil input sebagai array dari string kolom masing-masing dengan panjang yang sama. Jika ini melanggar aturan, tolong beri tahu saya. Ini menghasilkan 1 yang berarti menjalankan mario yang sukses, dan nilai lain yang menyiratkan menjalankan mario yang gagal.

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

Berikut ini adalah logika yang lebih lama (yang mirip dengan versi saat ini) dengan contoh penggunaan dan keluaran. Ditambah beberapa komentar yang menjelaskan logikanya

/**
 *
 * @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
sumber
@ Kararlast, Anda memang mendapatkan saya, tetapi test case yang diberikan benar. Masalahnya adalah bahwa op tidak menjelaskan apakah akan ada beberapa cara yang bisa dilakukan mario pada setiap langkah
Rohan Jhunjhunwala
Yah, saya berasumsi akan ada karena saya akan selalu menganggap versi yang lebih genral jika batasan tambahan tidak ditentukan.
KarlKastor
@KarlKastor, ya, benar
Rohan Jhunjhunwala
7

Python, 260 239 222 215 209 206 Bytes,

coba di ideone (dengan test case)

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

panggilan seperti: f([' S=', ' E='])

tambalan catatan:

Sekarang, seperti beberapa solusi lain, anggap input adalah array string kolom, masing-masing dimulai dengan ""

Wrapper untuk formulir input lama: g=lambda x:f(map("".join,zip(*([" "*x.index("\n")]+x.split("\n")))))

Juga, saya memperbaiki bug di mana Mario bisa melompati blok di atasnya.

versi ungolfed dengan penjelasan:

fsecara berulang menyebut dirinya ke segala arah yang bisa dituju Mario y,x. Ini kembali Trueketika mencapai "E"nd, yang kemudian kembali melalui semua panggilan fungsi sampai gakhirnya kembali 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
sumber
Jika melompat tidak membantu, Anda jatuh ke tanah. Tambahkan elsesebelum final return?
Titus
5

Siput , 41 37 29 byte

Terima kasih kepada feersum atas bantuannya untuk menghindari jalur yang tumpang tindih dan untuk menghemat 4 byte.

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

Membutuhkan input untuk diisi ke persegi panjang sehingga ada ruang di setiap sel yang Mario perlu lintasi (berpotensi dengan garis depan penuh spasi).

Cobalah online!

Penjelasan

Snails adalah entri feersum untuk tantangan desain bahasa pencocokan pola 2D kami. Seperti Slip, ini juga mirip dengan regex, tetapi perbedaan utama adalah a) yang satu ini mendukung pernyataan (lookaround) dan b) selain dari pernyataan ini, tidak mungkin untuk menelusuri sel dalam jaringan dua kali. Itu membuat masalah ini sedikit rumit, karena ada beberapa kasus di mana Mario harus jatuh ke dalam lubang dan melompat keluar, misalnya:

S E
= =
===

Terlepas dari perbedaan-perbedaan ini, sintaks dari kedua bahasa juga sangat berbeda.

Untuk menghindari masalah yang tidak dapat dilalui sel dua kali, kami selalu mengganti langkah horizontal dengan langkah vertikal. Namun, ini berarti bahwa kita harus menangani jatuh sebelum kita melangkahi langkan. Jadi air terjun akan secara teknis benar-benar melewati ubin tanah tetapi kami akan memastikan bahwa itu hanya terjadi di sebelah ruang terbuka.

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

C, 256 236 213 197 byte

20 byte disimpan oleh "Ini akan selalu muncul di kolom paling kiri dari input"
23 byte disimpan berkat sistem berbasis kolom @ RohanJhunjhunwala

Cobalah di ideone, dengan uji kasus ...

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

Pemakaian:

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

Tidak digabungkan dengan penjelasan:

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
sumber
Ideone mengatakan bahwa ada kesalahan runtime
TuxCrafting
6
Tunggu, Anda mengode pada ponsel ಠ_ಠ
TuxCrafting
4
Kamu, saya menumpahkan coke di laptop saya: P
betseg
1
(Tidak bermaksud betseg , hanya untuk memastikan keadilan) @ TùxCräftîñg: Apakah solusi ini sesuai dengan tantangan Anda karena dibutuhkan array String (sudah terpecah pada "\ n") dan juga memiliki panjang dan lebar input map (bukan bagian dari input dalam tantangan Anda)?
KarlKastor
2

PHP, 399 338 284 265 251 byte

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

mengharapkan input sebagai argumen baris perintah dengan jeda baris unix dan spasi tambahan di setiap baris, mengembalikan kode keluar 1untuk sukses, 0untuk kegagalan

kerusakan berfungsi

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
}

tes (pada fungsi 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
sumber
1
Kepada siapa pun: Akankah Anda memberi tahu saya mengapa Anda menurunkan ini?
Titus
2

Ruby, 153 147 byte

Maaf, Jawa ... tempat Anda sebagai bahasa non-golf terbaik untuk pekerjaan itu diambil alih!

Input adalah daftar string kolom, yang didahului dengan satu spasi dengan gaya bagaimana solusi Slip dan Siput membutuhkan input mereka untuk diisi dengan persegi panjang ruang kosong.

Cobalah 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]}}
Nilai Tinta
sumber
nooooo .... tapi kamu "meminjam" metode string kolumnar
Rohan Jhunjhunwala
1
Maksudku, semua anak keren sudah melakukannya. Mungkin kerajinan solusi berbasis baris nanti, melakukan "perbaikan cepat" untuk mengubah baris menjadi kolom untuk menjaga kode saya saat ini kehilangan ke Jawa Anda dengan 10 byte, tetapi solusi yang sebenarnya mungkin lebih pendek terlepas
Value Ink
2

Grime, 46 byte (tidak bersaing)

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

Saya telah memperbarui Grime beberapa kali setelah tantangan ini diposting, jadi jawaban ini tidak memenuhi syarat untuk menang. Beberapa perubahan sangat baru sehingga saya belum bisa memasukkannya ke TIO, tetapi begitu saya melakukannya, Anda dapat mencoba programnya . Bagaimanapun, repositori saya mengandung versi yang menangani kode ini dengan benar.

Program mencetak 1jika Mario dapat mencapai tujuan, dan 0jika tidak. Masukan harus berisi spasi di semua tempat yang perlu dikunjungi Mario. Untuk input umum, saya memiliki solusi 57-byte berikut :

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

Penjelasan

Penjelasan tingkat tinggi adalah bahwa nonterminal A, didefinisikan pada baris pertama, cocok dengan sub-persegi panjang 1 × 1 dari input di mana Mario dapat mencapai tujuan. Adidefinisikan sebagai literal E(Mario sudah di tujuan), atau sebagai pola 1 × 1 yang ada di kolom kiri beberapa persegi panjang 2 × n yang berisi lompatan Mario yang valid ke pertandingan lain Adi kolom kanan. Baris kedua menghitung jumlah kecocokan Ayang juga berisi karakter awal S, dan mencetaknya.

Berikut adalah rincian kode:

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.

Idenya adalah bahwa \ {,-4}bagian di sebelah kiri cocok dengan ruang di mana Mario melompat ke atas, dan \ /*bagian di sebelah kanan cocok dengan palung ruang di mana ia kemudian jatuh. Kami mengharuskan dia mendarat di pertandingan A(karena kami ingin mencapai tujuan) yang ada di atas a =. Tumpukan vertikal di bawah kedua kolom hanya akan menjamin bahwa kolom memiliki ketinggian yang sama, sehingga kita dapat menyatukannya (yang dilakukan oleh ruang tunggal di tengah). Berikut adalah diagram seni ASCII dari contoh lompatan, dipecah menjadi empat persegi panjang tersebut, dan dengan spasi diganti dengan *s:

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

Di baris kedua, opsi nmemicu penghitungan semua pertandingan, alih-alih menemukan pertandingan pertama. Dalam solusi umum, spasi juga bisa berupa karakter out-of-input khusus, dan opsib menyebabkan input diisi dengan karakter out-of-input.

Saya harap semua ini masuk akal!

Zgarb
sumber