Perl, 144 138 132 129 128 127 126 124 bayt
İçin +2 içerir -p0
Kod \0
, geçerli bir giriş karakteri (en azından içinde #
) olduğunu varsayar .
STDIN üzerindeki giriş ile çalıştırın:
surround.pl < surround.txt
surround.pl
:
#!/usr/bin/perl -p0
/^#[^#\0]/m&&s/^|[^#\n\0]\0/\0\0/mg,s%.%s/.(.*)/$+\0/g;/#/&&reverse"\n",/^./mg%seg until$?++<$$_++;y/\0/#/;s/^#*\n|#+$|^#//mg;y;#;
Kod olarak çalışıyor, ancak yerini \0
ve \n
iddia puan için onların literal versiyonlarını tarafından. Bir boşluk olduğuna dikkat edin
Satırın sonunda . Kod çok fazla döngü yapıyor, bu nedenle çıktı için 30 saniye beklemeniz gerekebilir.
açıklama
Tarafından \0
durdurulmuş ile bir taşkın dolgu yapacağım#
Ortogonal yönlerde dışarıdan . Bundan sonra #
kenarları kesip boşluklarla kalanları değiştireceğim. Taşkın dolgusundaki tüm yönleri ele almaktan kaçınmak için hedef alanı tekrar tekrar döndüreceğim ve sadece sağdan sola taşkın dolgu
/^#[^#\0]/m The rotation is written such that it slices
off the first column. That is ok unless the
first column contains a # that is followed by
something that could be the inside. There is
no newline inside the [] because short lines
will get extended during the rotation and
the character following the # will end
up as a \0 and match in a later round
&&s/^|[^#\n\0]\0/\0\0/mg In case the # could be an interior border I
will add two columns of \0's in front. One
will be a sacrifice for the rotation, the
other column will end up at the end of the area
after two rotations and function as seed for the
floodfill. This regex also does one step of
the floodfill from the back to the front.
After a certain number of loops we are certain
to get to a first column that must not be
dropped so at some point the last column is
guaranteed to consist of only \0. And we only need
to fill backward since the rotations will make
any direction backward at some point
s%.% process column %seg I will replace each character (including \n)
in the string by the next column in reversed
order or an empty string if there are no more
interesting columns. This is therefore a right
rotation. There are less columns than
characters so this loop is long enough
s%.%s/.(.*)/$+\0/g Remove the next (now first) character from each
row (so remove the column). Because the
original area is not necessarily a rectangle
add a \0 at the end of the row so we won't run
out out of columns (this would cause shorter
rows to have no entry in the new rotated row)
This will not do anything for empty lines so
they DO get squeezed out. But that is not a
problem since the problem statement says there
will be only one # shape so any empty lines
are can be safely dropped (this would not be
so if there could be multiple # shapes because
that could create a new surrounded area
/#/ Check if any of the remaining columns still
has a #. If not all remaining columns are on
the outside and can be dropped
&&reverse"\n",/^./mg Collect the column and add a \n to its reverse
until$?++<$$_++ Keep doing this until we get to a multiple of
65536 rotations when $? waraps back around to 0
(this is a multiple of 4 so the area is left
unrotated) and an area we have seen before
($$_ >= 1)
(so all slicing and flood filling is finished)
$_ having been seen in a previous rotations is
not a problem (though rather tricky to prove)
Bu noktada örn.
AB##J
E####GK
F# M #L
# N#O
P####
ile değiştirilecek:
0000000
0####00
0# M #0
# N#0
0####00
Temel olarak, doğrudan iç kısmı çevreleyen tüm sütunlar ve satırlar dilimlenmiştir. Kalan tüm dış karakterler \ 0 ile değiştirildi. Üstte ve sağda fazladan bir \ 0 katmanı var. Yani geriye kalan tek şey temizlik:
y/\0/#/ Replace any outside that is left by #
s/^#*\n|#+$|^#//mg Removes the first two and last line (the only
lines that can consist of purely #)
Removes any trailing #
Removes the first column of #
y;#; \n; Replace any remaining # by space since they
are needed to fill the concave parts
The final \n; is not written since it is implicit
in the -p loop
#
s çıkarın ve işte gidiyorsun ... ve sonra zorlaştı.