Perl 5 , -p0 105 101 96 93 90 89 byte
Gunakan bbukan 1pada input.
Pastikan matriks pada STDIN diakhiri dengan baris baru
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Cobalah online!
Gunakan 3 level subtitusi!
Versi 87 byte ini dalam format input dan output lebih mudah untuk diartikan, tetapi tidak bersaing karena menggunakan 3 karakter berbeda dalam output:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Cobalah online!
Sangat mudah untuk menyimpan byte lain ( spengubah regex ) di kedua versi dengan menggunakan beberapa karakter (non-alfanumerik) yang berbeda sebagai terminator baris (alih-alih baris baru), tetapi itu membuat input cukup tidak dapat dibaca lagi.
Bagaimana itu bekerja
Pertimbangkan substitusi
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Ini akan menemukan dua huruf yang berbeda dan bersebelahan secara horizontal atau vertikal dan menggantinya dengan c. Dalam labirin yang jalurnya terdiri dari seluruhnya huruf btidak akan terjadi karena huruf-hurufnya sama, tetapi segera setelah salah satu huruf diganti dengan yang lain (mis. z) Surat itu dan tetangga akan diganti oleh cdan aplikasi berulang adalah isi banjir komponen yang terhubung dengan cdari benihz .
Namun dalam hal ini saya tidak ingin banjir penuh. Saya hanya ingin mengisi salah satu lengan tetangga z, jadi setelah langkah pertama saya ingin yang zhilang. Itu sudah bekerja dengan c$2cpenggantian, tetapi saya kemudian ingin memulai kembali banjir-mengisi sepanjang lengan lain mulai dari titik yang sama dan saya tidak tahu yang mana dari cs awalnya z. Jadi alih-alih saya gunakan
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aadalah c, b | csedang cdan z | asedang {. Jadi dalam sebuah labirin dengan jalan setapak yang terbuat dari bdan sebuah benih zpada langkah pertama bakan digantikan oleh cdan zakan digantikan oleh {yang bukan huruf dan tidak cocok \wsehingga tidak akan menyebabkan pengisian lebih lanjut. The cnamun akan tetap banjir-fill lanjut pergi dan satu tetangga lengan benih akan diisi. Misalnya mulai dari
b c
b c
bbzbb becomes bb{bb
b b
b b
Saya kemudian dapat mengganti semua c dengan beberapa huruf (misalnya -) dan mengganti {dengan zlagi untuk memulai kembali pengisian banjir:
- -
- -
bbzbb becomes cc{bb
b b
b b
dan ulangi proses ini sampai semua tetangga benih telah bertobat. Jika saya sekali lagi ganti {dengan zdan isi banjir:
- -
- -
--z-- stays --z--
- -
- -
Yang ztertinggal di akhir karena tidak ada tetangga untuk melakukan transformasi dengan. Itu memperjelas apa yang terjadi dalam fragmen kode berikut:
/\n/ >
Temukan baris baru pertama. Offset awal sekarang dalam@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
Regex yang dibahas di atas dengan @{-}jumlah kolom (karena plain @-membingungkan parser perl dan tidak dapat diganti dengan benar)
&&
Yang /\n/selalu berhasil dan substitusi itu benar selama kita masih bisa mengisi banjir. Jadi bagian setelah &&dieksekusi jika mengisi banjir satu lengan dilakukan. Jika tidak sisi kiri mengevaluasi ke string kosong
y/{c/z / > 0
Nyalakan kembali isian banjir dan kembalikan 1 jika isian banjir sebelumnya melakukan sesuatu. Lain kembali string kosong. Seluruh bagian kode ini terbungkus di dalamnya
s:|.: code :seg
Jadi jika ini dieksekusi pada string awal $_dengan zposisi seed, potongan kode di dalamnya akan dieksekusi berkali-kali sebagian besar tidak menghasilkan apa-apa kecuali 1setiap kali lengan tetangga dipenuhi banjir. Secara efektif $_dihancurkan dan diganti oleh sebanyak 1komponen yang terhubung z. Perhatikan bahwa perulangan perlu dieksekusi hingga jumlah ukuran komponen + jumlah lengan, tetapi itu OK karena akan "jumlah karakter termasuk baris baru * 2 + 1" kali.
Labirin akan terputus jika tidak ada 1(string kosong, titik terisolasi) atau jika ada lebih dari 1 lengan (lebih dari 2 1detik). Ini dapat diperiksa menggunakan regex /\B/(ini memberikan 0bukan 1pada versi perl yang lebih lama. Ini bisa diperdebatkan mana yang salah). Sayangnya jika tidak cocok ini akan memberikan string kosong sebagai gantinya 0. Namun s:|.: code :segitu dirancang untuk selalu mengembalikan nomor ganjil sehingga dengan melakukan &dengan /\B/ini akan memberi 0atau 1.
Yang tersisa adalah berjalan seluruh array input dan pada setiap posisi benih berjalan dengan zdan menghitung lengan yang terhubung. Itu mudah dilakukan dengan:
s%b%$_="$`z$'"; code %eg
Satu-satunya masalah adalah bahwa dalam posisi non-walkable nilai lama dipertahankan. Karena kita memerlukannya 0di sana, itu berarti array input asli harus memiliki 0posisi yang tidak dapat dilalui dan 0cocok \wdengan subtitusi asli dan akan memicu banjir. Itu sebabnya saya menggunakan \pLsebagai gantinya (hanya huruf yang cocok).