Perl 103 + 2 = 105 байт
s/$/$"x y===c/gem;$a=$_;$_.=$"while$a=~s/^./!($_.=$&)/gem;s/$1/-/g,$b="$&$b"while/\s(\w)(\1|-)+ /;say$b
Запуск с -n0
(штраф 2 байта).
Объяснение:
# -n0: read entire input into `$_` at start of program
# (technically speaking it reads to the first NUL byte, but there aren't any)
# We want to be able to extract columns from the input, so we need to add spaces
# to the ends of each line such that each column is complete. Adding too many
# space is OK, so to ensure we have enough, we add a number of spaces equal to the
# length of the input.
s/$/ # At the end of {something},
$" x # append a number of spaces ($" is a space by default)
y===c # obtained by counting the characters in $_
/gem; # where {something} is each (g) line (m)
$a = $_; # store a copy of the transformed input in $a
# The next step is to create a transposition of the input. To do that, we
# repeatedly extract the first column of $a and append it to $_. This will lead to
# a bunch of junk whitespace at the end of $_ (of varying lengths, because once a
# line is empty it's omitted from the extracted column), but we're OK with that.
# To transpose properly, we'd want to place newlines between the extracted
# columns; however, it happens that the rest of the program treats space the same
# way it would newline, and separating via spaces is shorter, so we do that.
while ( # keep looping as long as there are matches
$a =~ s/^./ # replace the first character of {something related to $a}
!( # with the null string (NOT of something truthy)
$_.=$&) # but append that character ($&) to $_
/gem) { # {something} is each (g) line (m) of $a
$_.=$" # append a space ($", equivalent to newline here) to $_
}
# Finally, we repeatedly replace every character in the topmost line with the -
# character (treating a line as continuous through the - character but not through
# other characters), thus finding the lines from top to bottom. Because we
# appended the transpose of $_ to $_ above, each line appears twice: once
# horizontally, once vertically. We find only the horizontal copy, but replace
# both with hyphens.
# (Note: I rewrote the regex into a bit more readable of a form in this ungolfed
# version, because the original version wouldn't allow me room to write comments
# inside it. The two should be equivalent; I tested the golfed version.)
while ( # keep looping as long as there are matches
/\s(\w) # match a space or newline, $1 (a letter/digit/underscore),
(\1|-)+ # any positive number of $1s and hyphens,
\ /x) { # and a space
s/$1/-/g, # changes all $1s to spaces; set $& to $1, $1 becomes invalid
$b = "$&$b" # prepend $& to $b
}
# We need to output the lines from first (i.e. bottom) to last (i.e. top).
# We found them in the opposite order, but reversed them via prepending
# (not appending) the partial results to $b.
say $b # output $b
Здесь есть небольшая тонкость:
азбука
DDDDDDDDD
азбука
азбука
азбука
Посмотрите на четвертую строку здесь. Если бы порядок записи был BACBD, то там действительно могла бы быть горизонтальная линия B
s, не нарушая ни одного из предположений проблемы (кроме того, что есть только одна линия каждого цвета, что мы не проверяем). Чтобы обойти это, в последнем регулярном выражении мы гарантируем, что каждая строка начинается с буквы (или цифры, или подчеркивания, но это невозможно), и полагаемся на тот факт, что параллельные линии будут найдены слева направо и сверху -вниз (потому что регулярное выражение найдет первое совпадение в строке). Таким образом, первый символ каждой неоднозначной строки здесь перезаписывается до того, как сама строка рассматривается как совпадение, и это предотвращает сопоставление с регулярным выражением.