Mari kita membuat peta penjara bawah tanah

9

Dahulu kala, ketika saya menghabiskan lebih banyak waktu bermain RPG, salah satu masalah yang dimiliki beberapa pemain, adalah melacak pergerakan partai dan menggambar peta yang tepat. Jadi saya datang dengan ide, untuk memeriksa bagaimana kalian menghadapi masalah ini.

Tugas adalah menulis fungsi, yang mengambil sebagai input parameter daftar arah (dilewati sebagai struktur pilihan Anda) ^v<>, menampilkan peta ruang bawah tanah. Sebagai contoh untuk input: >>>vvv<<<^^^output akan:

+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+

Testcases

>>>>>>vvvvv<<<<^^^>>v



 +-------+
 |       |
 +-+---+ |
   |   | |
   | + | |
   | +-+ |
   |     |
   +-----+


^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^

          +-+ 
       +-+| | +-++-+
       | || | | ++ ++
       | ++ +-+     |
       |        +-+ |
       +--+ +-+ +-+-+
          | | |   |
          +-+ +---+

Karena tantangan kode golf, kode terpendek menang.

Selamat bermain golf.

EDIT Maaf untuk keterlambatan mengedit, saya tidak punya banyak waktu baru-baru ini.

Peta dihasilkan berdasarkan pergerakan. Seharusnya hanya berisi koridor yang dikunjungi selama berjalan. Karenanya menciptakan satu ruangan besar tidak akan menjadi jawaban yang valid.

Ada tiga simbol yang valid di peta:

  • | dinding vertikal
  • | dinding horizontal
  • + persimpangan dinding vertikal dan horizontal.

Panjang maksimum jalur adalah 255 karakter (tetapi jika Anda bisa, jangan batasi diri Anda sendiri).

Lebih banyak kasus uji:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

 +--+
 |  |
 |  |
 +--+

Saya harap sekarang semuanya jelas.

pengguna902383
sumber
3
Anda perlu memberikan deskripsi tugas. Kedua kasus uji bahkan tidak ditangani dengan cara yang tampak konsisten - yang pertama menambahkan wilayah yang terputus tanpa alasan yang jelas.
feersum
3
Contoh kedua Anda memiliki ruang tertutup, yang awalnya saya pikir adalah karena batas luar harus persegi panjang, tetapi kemudian contoh ketiga membantah gagasan itu. Silakan gunakan Sandbox untuk mendapatkan umpan balik tentang tantangan sebelum memposting.
El'endia Starman
2
Luar biasa. Saya masih menyarankan untuk menjadi eksplisit tentang bagaimana ruang bawah tanah dibangun dari gerakan.
El'endia Starman
1
Apa yang Anda maksud dengan "peta tampilan"? Apakah mengembalikan peta dari fungsi diperbolehkan?
Paul Schmitz
3
Ini terlihat menarik. Adakah kesempatan untuk mengedit agar dibuka kembali? Hal-hal yang perlu dilihat secara khusus: dari contoh, sepertinya Anda tidak keberatan dengan ruang kosong tambahan di sekitar output tetapi akan lebih baik untuk memperjelas. Juga jika Anda secara eksplisit menggambarkan penampilan dinding dan menjawab pertanyaan susu itu harus membuat pertanyaan itu cukup jelas. Satu hal yang saya pikir belum Anda bahas adalah output apa yang vvv>>^^^<<akan dihasilkan (melintasi? Pipa?)
Dave

Jawaban:

3

Javascript (ES6), 261 254 243 byte

s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=`
`));return z}

JSFiddle

Arnauld
sumber
Anda dapat menghapusnya returndengan mengganti ;dengan ,dan {}dengan()
Cyoce
@Cyoce - Ada forloop di sana yang tidak bisa disematkan dengan cara itu.
Arnauld
lalu ganti {dengan eval("dan }dengan ")untuk menghapus codegolf kembali.stackexchange.com/a/80967/41042
Cyoce
@Cyoce - Sayangnya, saya pikir saya harus melarikan diri dari linebreak literal seolah- '\\n'olah saya melakukannya. Jika saya hitung dengan benar, itu sebenarnya mengarah ke +1 byte. Atau adakah cara yang lebih baik untuk menanamkan linebreak dalam eval?
Arnauld
Anda hanya perlu \nkarena string template mendukung baris baru secara literal, tetapi itu masih akan meninggalkannya pada jumlah byte yang sama. Oh well
Cyoce
3

C, 246 byte

n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}

Mengambil input sebagai karakter yang terpisah, misalnya:

./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'

Atau lebih mudahnya, format ini (tanpa tanda kutip!):

./mapper $(echo '>>>vvv<<<^^^' | fold -w1)

Atau untuk input acak (sangat tidak efisien):

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)

Dan akhirnya, menggunakan awkuntuk memotong hasilnya berarti kita bisa menjadi lebih besar:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'

 +-----+
 |     |
 |     +-+  +-----+
 |       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
 +-+               +--+
 |     ++             |
 +-+  +-++           +-+
   ++   |+--+          |
    +-+ | |        ++  |
     ++ | ++   + +--+ ++
     |  |  +---|      |
     |  |     ++  +---+
     ++ |-+   |   |
      | | +--+-+  |
      | +    +    |
      |        +--+
      +--------+

Output ke stdout. Menggunakan fakta bahwa padding diperbolehkan di sekitar peta (menghasilkan peta yang memiliki panjang tepi 2 * n + 1, menempatkan posisi akhir di tengah).

Kerusakan

Ini bekerja dengan mengulangi argumen secara terbalik dan bergerak mundur. Sebenarnya menggunakan fakta bahwa arg 0 adalah nama program; tidak peduli apa namanya, tetapi memungkinkan kita untuk mengunjungi sel awal dan terakhir (serta semua sel di antaranya) tanpa perlu penanganan khusus.

n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
    for(                            // Step 1: identify visited cells
        n=c*2+3,                    //  Set output grid size
        g=calloc(n*n,8),            //  Allocate map storage space
        p=g+(n+1)*(c+1);            //  Start at centre
        c--;                        //  Loop over directions in reverse
        y=*v[c],                    //  Get current direction
        p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
    )*p=1;                          //  Mark cell visited
    for(y=n-1;--y;)                 // For each row (except edges)
        for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
            putchar(c?" |-++|-+"[   //   Print wall using lookup table
                *p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
            ]:10)                   //   Or newline
        )p=g+y*n+c;                 //   Set current cell (happens first)
}
Dave
sumber