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
модификатор regex ) в обеих версиях, используя какой-либо другой (не буквенно-цифровой) символ в качестве разделителя строк (вместо новой строки), но это делает ввод снова совершенно нечитаемым.
Как это устроено
Рассмотрим замену
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
Затем я могу заменить все с на некоторых не буквы (например -
) и заменить {
на z
еще раз , чтобы перезапустить Flood-заливку:
- -
- -
bbzbb becomes cc{bb
b b
b b
и повторяйте этот процесс, пока все соседи семени не будут обращены. Если бы я тогда еще раз заменить {
на z
и наводнения заполнения:
- -
- -
--z-- stays --z--
- -
- -
В z
остается за в конце , потому что нет соседей , чтобы сделать преобразование с. Это проясняет, что происходит в следующем фрагменте кода:
/\n/ >
Найдите первую новую строку. Начальное смещение теперь в@-
s#(\w)(.{@{-}}|)(?!\1)(\w)#$&|a.$2.a#se
Вышеуказанное регулярное выражение с @{-}
числом столбцов (так как plain @-
путает парсер perl и не заменяет его должным образом)
&&
/\n/
Всегда преуспевает и замена верна до тех пор , как мы можем все еще наводнение заполнения. Таким образом, часть после &&
выполняется, если заполнение одной руки выполнено. Если нет, то левая сторона вычисляется как пустая строка
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
вместо этого (только совпадающие буквы).