Perl 5 , -p0 105 101 96 93 90 89 байт
Використовується bзамість 1введення.
Переконайтесь, що матриця на STDIN закінчується новим рядком
#!/usr/bin/perl -p0
s%b%$_="$`z$'";s:|.:/
/>s#(\pL)(.{@{-}}|)(?!\1)(\pL)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Спробуйте в Інтернеті!
Використовує 3 рівні заміщення!
Ця 87-байтна версія і в форматі вводу, і у виході простіша для інтерпретації, але не конкурує, оскільки у виводі використовується 3 різних символи:
#!/usr/bin/perl -0p
s%b%$_="$`z$'";s:|.:/
/>s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se&&y/{c/z />0:seg&/\B/%eg
Спробуйте в Інтернеті!
Зберегти інший байт ( sмодифікатор регулярного виразів) в обох версіях легко , використовуючи в якості термінатора рядків (замість нового рядка) деякі різні (не буквено-цифрові) символи, але це робить введення знову нечитабельним.
Як це працює
Розглянемо підміну
s#(\w)(.{columns}|)(?!1)(\w)#c$2c#s
Тут ви знайдете дві букви, які є різними та розташовані поруч один з одним по горизонталі чи вертикалі, і замініть їх на c. У лабіринті, шлях якого повністю складається з літери, bнічого не відбудеться, оскільки букви однакові, але як тільки одна з букв буде замінена на іншу (наприклад z), цей лист і сусід будуть замінені на cповторне застосування заливка з’єднаного компонента з cнасінням z.
Однак у цьому випадку я не хочу повного заповнення. Я хочу заповнити лише одну із сусідніх озброєнь z, тому після першого кроку я хочу zпіти. Це вже працює з c$2cзаміною, але пізніше я хочу перезапустити заливку уздовж іншої руки, починаючи з тієї ж точки, і я не знаю, хто з cs спочатку zвже не був. Тому замість цього я використовую
s#(\w)(.{columns}|)(?!\1)(\w)#$&|a.$2.a#se
b | aє c, b | cє cі z | aє {. Тож у лабіринті зі складеними доріжками bта насінням zна першому кроці bзаміняться cі zзаміняться {котрими не буквою і не збігаються \wі тому не спричинять подальших заповнень. cОднак буде продовжувати подальший Flood-заливку збирається і один сусід руки насіння заповнюється. Наприклад, починаючи з
b c
b c
bbzbb becomes bb{bb
b b
b b
Тоді я можу замінити всі c деякими літерами (наприклад -) і замінити {ще zраз, щоб перезапустити заливку:
- -
- -
bbzbb becomes cc{bb
b b
b b
і повторюйте цей процес, поки не перетворяться всі сусіди насіння. Якби я тоді ще раз замінити {на zі повені заповнення:
- -
- -
--z-- stays --z--
- -
- -
В zзалишається за в кінці , тому що немає сусідів , щоб зробити перетворення с. Це дає зрозуміти, що відбувається в наступному фрагменті коду:
/\n/ >
Знайдіть перший рядок. Початкове зміщення зараз у@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
Регекс, обговорений вище, @{-}як кількість стовпців (оскільки звичайна @-плутає парсер-аналізатор і не належним чином замінює)
&&
/\n/Завжди добре ведеться і заміна вірна до тих пір , як ми можемо все ще повінь заповнення. Тож частина after &&виконується, якщо виконана заливка однієї руки. Якщо ні, ліва сторона оцінює порожній рядок
y/{c/z / > 0
Перезапустіть заливку та поверніть 1, якщо попереднє заливне читання щось зробило. В іншому поверніть порожній рядок. Весь цей фрагмент коду загорнутий всередину
s:|.: code :seg
Отже, якщо це виконується на початковій рядку $_з zпозицією насіннєвого елемента, фрагмент коду всередині буде виконуватися багато разів, здебільшого не повертаючи нічого, окрім 1кожного разу, коли сусідня рука заповнюється затопленою. Ефективно $_знищується та замінюється на стільки 1, на скільки приєднані підключені компоненти z. Зауважте, що цикл потрібно виконати до суми розмірів компонентів + кількості разів на озброєння, але це нормально, оскільки це "кількість символів, включаючи нові рядки * 2 + 1" разів.
Лабіринт відключається, якщо немає 1(порожня рядок, ізольована вершина) або якщо є більше 1 руки (більше 2 1с). Це можна перевірити, використовуючи регулярний вираз /\B/(це дає 0замість 1старих версій perl. Сперечається, який з них неправильний). На жаль, якщо це не відповідає, це дасть порожній рядок замість 0. Однак s:|.: code :segбув розроблений , щоб завжди повертати непарне число так, виконавши &з /\B/це дасть 0або 1.
Залишилося лише пройти весь вхідний масив і в кожній прохідній позиції посіяти з zпідрахунком і підключити руки. Це легко зробити за допомогою:
s%b%$_="$`z$'"; code %eg
Єдина проблема полягає в тому, що в положеннях, які не мають змоги зберігати, зберігається старе значення. Оскільки нам потрібен 0s, це означає, що оригінальний вхідний масив повинен 0знаходитись у положеннях, що не готуються, та 0збігаються \wв оригінальній підстановці і спричинить заповнення. Тому я використовую \pLнатомість (лише відповідні букви).