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
заміною, але пізніше я хочу перезапустити заливку уздовж іншої руки, починаючи з тієї ж точки, і я не знаю, хто з c
s спочатку 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
Єдина проблема полягає в тому, що в положеннях, які не мають змоги зберігати, зберігається старе значення. Оскільки нам потрібен 0
s, це означає, що оригінальний вхідний масив повинен 0
знаходитись у положеннях, що не готуються, та 0
збігаються \w
в оригінальній підстановці і спричинить заповнення. Тому я використовую \pL
натомість (лише відповідні букви).