Roguelike mencari jalan

21

Roguelike mencari jalan

Tugas Anda akan, diberikan array dua dimensi dari elemen yang dijelaskan di bawah ini, yang mewakili ruang bawah tanah, untuk menghasilkan atau mengembalikan nomor tunggal yang mewakili jumlah keping emas yang dapat dikumpulkan oleh penjahat tanpa membangunkan monster apa pun.

Elemen-elemen array adalah sebagai berikut:

  1. Ruang kosong diwakili oleh salah satu .atau satu ruang, panggilan Anda;
  2. Posisi awal Rogue diwakili oleh, tentu saja @,;
  3. Sepotong emas diwakili oleh $;
  4. Dinding diwakili oleh #;
  5. Monster diwakili oleh karakter dari regexp berikut: [a-zA-Z*&].

Array tidak boleh mengandung karakter apa pun yang tidak tercantum di atas, sehingga Anda dapat mengasumsikan bahwa apa pun yang bukan dinding, ruang kosong, bajingan, atau keping emas adalah monster.

Aturan untuk merintis jalan adalah:

  1. Si nakal hanya bisa berjalan melalui sel-sel kosong atau sel-sel yang mengandung emas;
  2. Dibutuhkan belokan untuk bergerak ke sel yang berdekatan atau berdekatan secara diagonal;
  3. Mengambil emas itu instan;
  4. Si nakal tidak bisa tetap berdekatan atau berdekatan secara diagonal dengan monster selama lebih dari satu putaran tanpa membangunkannya, yang dilarang;
  5. Si nakal dapat memasuki area kesadaran monster beberapa kali, monster itu hanya akan bangun jika si nakal menghabiskan dua putaran berturut-turut di dekatnya.

Aturan input dan output

Anda bisa mendapatkan input dalam format apa pun yang masuk akal, termasuk array dua dimensi, array datar, string, atau apa pun. Jika itu membuat hidup Anda lebih mudah, Anda juga dapat mengambil dimensi array.

Dijamin bajingan itu tidak akan berada di dekat monster di awal.

Program atau fungsi lengkap tidak masalah.

Mencetak gol

Ini adalah , skornya adalah jumlah byte dari kiriman Anda dengan lebih sedikit yang lebih baik.

Uji kasus

Saya menggunakan titik-titik untuk ruang kosong di sini untuk tujuan keterbacaan, jika Anda ingin Anda dapat menggunakan spasi (lihat di atas). Perhatikan juga bahwa ini adalah kebetulan murni bahwa bajingan itu selalu berada di sudut kiri atas, kode Anda harus menangani posisi valid lainnya juga.

1)
@..
.$.
...  -> 1

Hanya tes kewarasan.

2)
@....
...g$
.....  -> 0

Sekali lagi, tes kewarasan.

3)
@....
...$g
.....  -> 1

Si nakal dapat mengambil emas dengan bergerak dari kiri.

4)
@....g..
.......$
........
.....h..  -> 1

Si bajingan dapat berzigzag di antara para monster, tidak pernah tinggal lebih dari satu belokan di dekat masing-masing monster.

5)
@....z..
.......$
.....b..  -> 0

Taktik dari test case sebelumnya tidak berfungsi di sini - area sensitivitas monster tumpang tindih.

6)
@$#.
###$
....  -> 1

Tes kewarasan.

7)
@..#..
$.$g.$
...#..  -> 2

Dito.

8)
@#.d#$
$...##
e.....
..$...
##..$b
.#..g$  -> 3

Dari semua emas di sini, hanya tiga yang dapat dicapai dengan aman: emas di dekat posisi awal dapat diperoleh dengan memindahkan satu dan kemudian kembali ke posisi awal. Untuk melarikan diri dari sudut kiri atas bajingan harus bergerak secara diagonal ke kanan bawah dua kali. Emas di tengah tidak menimbulkan tantangan. Emas terluar dijaga oleh gdan bbisa didapat dengan bergerak secara diagonal dari tempat ke kanan emas tengah dan kemudian kembali. Sisanya tidak dapat diperoleh: emas kanan atas diblokir oleh dinding, dan emas kanan bawah membutuhkan dua belokan di area sensitivitas monster.

Kasus uji berikut ini disumbangkan dengan murah hati oleh mbomb007.

9)
  12345678
a @....g.D
b .......$
c ......#.
d .....h..  -> 1

Yang ini rumit. Sebuah jalan adalah b4-b5-c6-b7-c8-b8(grab).

10)
  12345678
a @....g.D
b .......$
c .......#
d .....h..  -> 1

Sebuah jalan adalah [bc]4-c5-b6-c7-b8(grab).

11)
  12345678
a @....g.D
b ......#$
c .......#
d .....h..  -> 1

Dinding ekstra tidak benar-benar mengubah apa pun, [bc]4-c5-b6-c7-b8(grab)masih merupakan solusi.

Michail
sumber
Anda harus menambahkan contoh yang lebih besar dan lebih kompleks. Juga, apa dimensi minimum dan maksimum dari ruang bawah tanah? Apakah penjara 1x1 @input yang valid?
mbomb007
@ mbomb007 Saya telah menambahkan contoh baru. Mengenai ukuran grid, saya pikir membatasi setidaknya 3x3 masuk akal.
Michail
@ mbomb007 Keberatan jika saya mengedit contoh Anda? Mereka, begitu mengerti, menunjukkan logika dengan sangat baik.
Michail
Merasa bebas. Untuk itulah saya membuatnya. Dapat juga dicatat bahwa memutar test case seharusnya tidak berdampak pada hasilnya.
mbomb007

Jawaban:

5

solusi sebelumnya (sebagian dari mereka) dapat ditemukan di wadah footer di tautan tio (itu mungkin lebih mudah dibaca)

JavaScript (Node.js) , 883 436 411 360.345 311 byte

g=>g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A
P=(g,x,y,m={},p={},I=i=9,M={})=>{if(/[.$]/.test(c=(g[y]||0)[x])){for(;i--;)if(/^[^.@$#]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])){if(m[C])return
M[C]=1}for(;I--;)if(!p[(X=x+~-(I/3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return 1}return c=="@"}

Cobalah online!

Penjelasan -

alih-alih beralih dari pemain ke uang tunai, saya beralih dari kasing ke @. saya pikir saya harus lebih cepat karena saya tahu kapan harus berhenti mencari (mencapai @), dan ketika Anda mencari uang tunai Anda harus selalu bergerak sampai Anda menutupi semua tempat (dan cara untuk sampai ke sana). jadi algo cukup sederhana seperti itu - fungsi utama g.map((r,y)=>[...r].map((c,x)=>A+=c=="$"&&P(g,x,y)),A=0)|A: cari uang tunai -> jika Anda menemukannya -> mulai mencari pemain -> jika Anda menemukannya -> kenaikan A sekarang mari kita ke path finder alias P if(/[.$]/.test(c=(g[y]||[])[x]))hanya periksa apakah sel saat ini adalah "spesial" -> jika demikian kami ingin kembali jika ini adalah pemain. kasus khusus: @ # (monster)

for(;i--;) if(/^[a-zA-Z*&]$/.test(C=(g[y+~-(i/3)]||0)[x+i%3-1])) -> if my neighbor is a monster {if(m[C])return false -> and it already was in the previous turn - this path is not value M[C]=1} -> if not just add it to the neighbors monsters for(;I--;) if(!p[(X=x+~-(I / 3))+","+(Y=y+I%3-1)]&&P(g,X,Y,M,{...p,[x+","+y]:1}))return true beralih kembali ke tetangga - jika saya belum ada di sana (p adalah jalur yang diambil) lanjutkan jalan (panggilan P)

DanielIndie
sumber
Golf yang bagus! Beberapa hal yang saya perhatikan: (1) kode Anda memiliki spasi spasi berlebihan pada baris ke-2 dan ke-7, dan sebagian besar jeda baris tidak perlu (hanya baris 1 dan 6 yang perlu istirahat), dan I / 3memiliki ruang yang tidak perlu. Hilangkan ruang putih itu dan skor Anda sebenarnya 324! (2) return true dapat menjadi return 1(nilai yang benar) dan return falsedapat secara sederhana return(tersirat undefined, nilai yang palsu). (3) Regex ^[^.@$#]$untuk memeriksa tidak ada monster lebih pendek daripada ^[a-zA-Z*&]$memeriksa monster. Kerja bagus!
apsillers
ya saya tahu saya bisa membuatnya jauh lebih pendek :)
DanielIndie
@apsillers diperbarui ke ruang bebas solusi :)
DanielIndie