Perl 5 , -p0
105 101 96 93 90 89 byte
Gunakan b
bukan 1
pada 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 ( s
pengubah 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 b
tidak 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 c
dan aplikasi berulang adalah isi banjir komponen yang terhubung dengan c
dari 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 z
hilang. Itu sudah bekerja dengan c$2c
penggantian, tetapi saya kemudian ingin memulai kembali banjir-mengisi sepanjang lengan lain mulai dari titik yang sama dan saya tidak tahu yang mana dari c
s awalnya z
. Jadi alih-alih saya gunakan
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | a
adalah c
, b | c
sedang c
dan z | a
sedang {
. Jadi dalam sebuah labirin dengan jalan setapak yang terbuat dari b
dan sebuah benih z
pada langkah pertama b
akan digantikan oleh c
dan z
akan digantikan oleh {
yang bukan huruf dan tidak cocok \w
sehingga tidak akan menyebabkan pengisian lebih lanjut. The c
namun 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 z
lagi 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 z
dan isi banjir:
- -
- -
--z-- stays --z--
- -
- -
Yang z
tertinggal 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 z
posisi seed, potongan kode di dalamnya akan dieksekusi berkali-kali sebagian besar tidak menghasilkan apa-apa kecuali 1
setiap kali lengan tetangga dipenuhi banjir. Secara efektif $_
dihancurkan dan diganti oleh sebanyak 1
komponen 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 1
detik). Ini dapat diperiksa menggunakan regex /\B/
(ini memberikan 0
bukan 1
pada 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 :seg
itu dirancang untuk selalu mengembalikan nomor ganjil sehingga dengan melakukan &
dengan /\B/
ini akan memberi 0
atau 1
.
Yang tersisa adalah berjalan seluruh array input dan pada setiap posisi benih berjalan dengan z
dan 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 0
di sana, itu berarti array input asli harus memiliki 0
posisi yang tidak dapat dilalui dan 0
cocok \w
dengan subtitusi asli dan akan memicu banjir. Itu sebabnya saya menggunakan \pL
sebagai gantinya (hanya huruf yang cocok).