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заменой, но позже я хочу перезапустить заливку вдоль другой руки, начиная с той же точки, и я не знаю, какой из 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
Затем я могу заменить все с на некоторых не буквы (например -) и заменить {на 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
Единственная проблема заключается в том, что в неприступных позициях сохраняется старое значение. Так как нам нужно 0s, это означает, что исходный входной массив должен находиться 0в непригодных для прохода позициях и 0совпадениях \wв исходной замене и вызывать заливки. Вот почему я использую \pLвместо этого (только совпадающие буквы).