Лабиринт задается в виде матрицы 0 (стены) и 1 (пройденное пространство) в любом удобном формате. Каждая ячейка считается связанной со своими 4 (или менее) ортогональными соседями. Подключенный компонент представляет собой набор проходимых клеток все транзитивно соединенных друг с другом. Ваша задача - определить точки среза - проходные ячейки, которые, если превратиться в стены, изменит количество подключенных компонентов. Выведите логическую матрицу с 1-й только в этих местах. Цель состоит в том, чтобы сделать это с наименьшим количеством байтов кода.
Входная матрица будет состоять как минимум из 3 строк и 3 столбцов. По крайней мере одна из его клеток будет стеной, и по крайней мере одна будет проходной. Ваша функция или программа должны быть в состоянии обработать любой из приведенных ниже примеров в течение минуты на TIO (или на вашем собственном компьютере, если язык не поддерживается TIO).
in:
11101001
11011101
00000001
11101111
11110101
00011111
10110001
11111111
out:
01000000
00001001
00000001
00000101
00110000
00010000
00000000
11100000
in:
1111111111111111
1000000000000001
1111111111111101
0000000000000101
1111111111110101
1000000000010101
1011111111010101
1010000001010101
1010111101010101
1010101111010101
1010100000010101
1010111111110101
1010000000000101
1011111111111101
1000000000000001
1111111111111111
out:
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
0000000000000000
in:
1011010001111010
1111111011101101
1110010101001011
1111001110010010
1111010000101001
0111101001000101
0011100111110010
1001110011111110
0101000011100011
1110110101001110
0010100111000110
1000110111011010
0100101000100101
0001010101100011
1001010000111101
1000111011000010
out:
0000000000111010
1011110001001000
0000000000000011
0000000100010000
0000010000101000
0000001000000100
0000000011000000
1001100000011110
0000000001000010
0110100001000110
0000100101000010
1000100000000000
0100001000000100
0000000100100001
0000010000111000
0000010000000010
Ответы:
Stax , 40 байт
Запуск и отладка тестовых случаев
Эта программа принимает ввод как разделенную пробелами строку, содержащую строки. Вывод в том же формате. Вот распакованное представление ascii.
Основная операция для подсчета острова работает следующим образом.
'1'
на'2'
.'12|21'
на'22'
.'1'
в строке больше не будет a . Количество повторений - это количество островов.,
Бонусная 44-байтовая программа - эта версия вводит и выводит, используя формат сетки.
источник
MATL , 26 байт
Ввод представляет собой числовую матрицу, используя в
;
качестве разделителя строк.Попробуйте онлайн! Или проверьте все тестовые случаи .
объяснение
источник
Perl 5 ,
-p0
10510196939089 байтИспользуется
b
вместо1
ввода.Убедитесь, что матрица на STDIN завершена с новой строки
Попробуйте онлайн!
Использует 3 уровня замещения!
Эта 87-байтовая версия и во входном, и в выходном формате проще для интерпретации, но не конкурирует, поскольку в выводе используются 3 разных символа:
Попробуйте онлайн!
Легко сохранить другой байт (
s
модификатор regex ) в обеих версиях, используя какой-либо другой (не буквенно-цифровой) символ в качестве разделителя строк (вместо новой строки), но это делает ввод снова совершенно нечитаемым.Как это устроено
Рассмотрим замену
Это позволит найти две разные буквы, расположенные рядом друг с другом по горизонтали или вертикали, и заменить их на
c
. В лабиринте, пути которого состоят полностью из буквы,b
ничего не произойдет, так как буквы одинаковы, но как только одна из букв будет заменена другой (например,z
эта буква и сосед будут заменены,c
и повторное применение будет заливка подключенного компонентаc
из семянz
.Однако в этом случае я не хочу полной заливки. Я хочу заполнить только одно соседнее оружие
z
, поэтому после первого шага хочуz
уйти. Это уже работает сc$2c
заменой, но позже я хочу перезапустить заливку вдоль другой руки, начиная с той же точки, и я не знаю, какой изc
s былz
больше. Так что вместо этого я используюb | a
естьc
,b | c
естьc
иz | a
есть{
. Таким образом , в лабиринте с дорожками, состоящими изb
и семеитеz
на первом этапеb
будет получать замененыc
иz
получите заменены{
что не буква и не соответствует ,\w
и поэтому не будет причиной дальнейших заливок.c
Однако будет продолжать дальнейший Flood-заливку собирается и один сосед руки семени заполняется. Например, начиная сЗатем я могу заменить все с на некоторых не буквы (например
-
) и заменить{
наz
еще раз , чтобы перезапустить Flood-заливку:и повторяйте этот процесс, пока все соседи семени не будут обращены. Если бы я тогда еще раз заменить
{
наz
и наводнения заполнения:В
z
остается за в конце , потому что нет соседей , чтобы сделать преобразование с. Это проясняет, что происходит в следующем фрагменте кода:Найдите первую новую строку. Начальное смещение теперь в
@-
Вышеуказанное регулярное выражение с
@{-}
числом столбцов (так как plain@-
путает парсер perl и не заменяет его должным образом)/\n/
Всегда преуспевает и замена верна до тех пор , как мы можем все еще наводнение заполнения. Таким образом, часть после&&
выполняется, если заполнение одной руки выполнено. Если нет, то левая сторона вычисляется как пустая строкаПерезапустите заливку и верните 1, если предыдущая заливка что-то сделала. В противном случае верните пустую строку. Весь этот кусок кода обернут внутри
Таким образом, если это выполняется для начальной строки
$_
сz
начальной позицией, то фрагмент кода внутри будет выполняться много раз, в основном, ничего не возвращая, кроме как1
каждый раз, когда соседняя ветвь заполняется. Эффективно$_
уничтожается и заменяется столько же,1
сколько подключенных компонентовz
. Обратите внимание, что цикл должен быть выполнен с точностью до суммы размеров компонентов + количества тактов, но это нормально, так как он будет «количество символов, включая переводы строки * 2 + 1».Лабиринт отключается, если нет ни одного
1
(пустая строка, изолированная вершина) или если имеется более 1 руки (более 21
с). Это можно проверить с помощью регулярного выражения/\B/
(это дает0
вместо1
старых версий Perl. Можно утверждать, что это не так). К сожалению, если он не совпадает, вместо него выдается пустая строка0
. Однако онs:|.: code :seg
был разработан, чтобы всегда возвращать нечетное число, поэтому, сделав&
с/\B/
этим, вы получите0
или1
.Все, что осталось, - это пройти весь входной массив и в каждой проходной позиции начать с
z
подсчета и подключенных рук. Это легко сделать с помощью:Единственная проблема заключается в том, что в неприступных позициях сохраняется старое значение. Так как нам нужно
0
s, это означает, что исходный входной массив должен находиться0
в непригодных для прохода позициях и0
совпадениях\w
в исходной замене и вызывать заливки. Вот почему я использую\pL
вместо этого (только совпадающие буквы).источник
Ява 8,
503489459455 байт-18 байт благодаря @ceilingcat .
Объяснение:
Попробуйте онлайн.
источник
Python 2 , 290 байт
Попробуйте онлайн!
-11 байт благодаря Роду
-11 байт благодаря Линн
источник
F(m,i,j)
для каждого элемента, экономя 11 байтовfor q in((i,j+1),(i,j-1),(i+1,j),(i-1,j)):
->for q in(i,j+1),(i,j-1),(i+1,j),(i-1,j):
- rm внешниеF
неявно возвращаетNone
, вы можете использоватьF(m,i,j)or c
вместо[F(m,i,j)]and c
.and m[i][j]
может быть>0<m[i][j]
и[q[:]for q in m]
может бытьeval(`m`)
.Wolfram Language (Mathematica) , 118 байт
Попробуйте онлайн!
источник
Javascript 122 байта
Ввод / вывод в виде многострочной строки.
Для каждой клетки, которую можно пройти, поместите блок и попробуйте заполнить 4 соседние клетки. Если текущая ячейка не является точкой обрезки, то, начиная с любого открытого соседа, все они будут заполнены. Иначе мне понадобится более одной операции заполнения, чтобы добраться до всех соседних ячеек.
Меньше гольфа
Тестовое задание
источник