Que es estar rodeado

18

Siempre quise rodear un texto con #s, pero tengo problemas para entender lo que rodeé, por lo que en este desafío escribirás un programa para hacer exactamente eso

Ejemplos

Las entradas / salidas están separadas por una nueva línea.

###
#a#
###

a
 #
#a#
 #

a
  ###  
 # a #
# b c #
#######

  a 
 b c 
ABCDHIJ
E####GK
F# M #L
#   N#O
P####

  M 
   N
###A###
#C#B#o#
#d###e#
 # go#
  ###

C   o
d   e
  go

Especificaciones

  • #s son los que "rodean" un bloque de texto
  • # siempre estarán adyacentes entre sí (incluso en diagonal)
  • # siempre formará una forma cerrada
  • Solo habrá una #forma
  • En el caso de una forma cóncava, los agujeros deben rellenarse con espacios.
  • El espacio en blanco debe conservarse en la salida
Downgoat
fuente
al principio pensé ... solo saca el #s y ahí lo tienes ... y luego se puso difícil.
Calvo Bantha
Tengo problemas para obtener entradas en JavaScript y dividirlas por nueva línea ... ¿cómo debo obtener entradas? ¿podría formatearse con un \ndespués de cada línea de entrada y pasar como parámetro de función a mi programa o qué?
Bald Bantha
1
¿Cuál es el conjunto de caracteres de entrada válidos?
Ton Hospel
¿Hay algún error en la salida del ejemplo MN ? Su salida consiste solo en el texto rodeado _M_\n___N(usando guiones bajos en lugar de espacios debido a problemas de formato), mientras que en los ejemplos abc y Codego la salida también incluye espacios en blanco donde #s estaban en la entrada. Si solo se va a imprimir el texto rodeado por #s, la salida del ejemplo abc debería ser _a_\n_b_c_(en lugar de __a_\n_b_c) y la salida del ejemplo de Codego debería ser Co\nde\n_go(en lugar de C___o\nd___e\n__go).
epidemia
@epidemian ah, buena captura. He arreglado el MNejemplo. ya que no de debe sido un espacio adicional después M.
Downgoat

Respuestas:

6

Perl, 144 138 132 129 128 127 126 124 bytes

Incluye +2 para -p0

El código asume \0que no es un carácter de entrada válido (al menos dentro de #).

Ejecutar con la entrada en STDIN:

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;#; 

El código funciona como es, pero reemplaza el \0y \npor sus versiones literales para la puntuación reclamada. Observe que hay un espacio al final de la línea. El código se repite demasiadas veces, por lo que puede que tenga que esperar 30 segundos más o menos para la salida.

Explicación

Voy a hacer un relleno con \0parada #desde el exterior en las direcciones ortogonales. Después de eso, cortaré los #lados y reemplazaré todo lo que quede por espacios. Para evitar tener que manejar todas las direcciones en el relleno, rotaré repetidamente el área objetivo y solo el relleno de derecha a izquierda

/^#[^#\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)

En este punto, por ejemplo

AB##J
E####GK
F# M #L
#   N#O
P####

habrá sido reemplazado por:

0000000
0####00
0# M #0
#   N#0
0####00

Básicamente, todas las columnas y filas que no bordean directamente el interior se han cortado. Los caracteres externos que quedan se han reemplazado por \ 0. En la parte superior y derecha hay una capa adicional de \ 0. Entonces, todo lo que queda es la limpieza:

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
Ton Hospel
fuente
¿Sus rellenos funcionan alrededor de las esquinas interiores, si hubiera alguna?
mbomb007
@ mbomb007: Sí, dado que el área se gira repetidamente, por lo que puede seguir los corredores sinuosos. El bucle que se detiene demasiado pronto antes de reducir paredes muy gruesas es el único defecto que yo sepa
Ton Hospel
@ mbomb007: Aaaa y la gruesa falla de la pared ahora está resuelta
Ton Hospel
copie y pegue su solución tal como está (sin reemplazar los caracteres escapados), la salida es simplemente la entrada con todo #despojado. verifique mi sesión de bash: codepad.org/YbCzB4O4
ardnew
@ardnew: Vaya, lo siento. Para la última actualización no repasé la solución completa, y debería haber reemplazado el while por un while. Corregido ahora, inténtalo de nuevo
Ton Hospel
4

Javascript, 485 464 427 417 396 390 bytes

s='indexOf';k='lastIndexOf';h="#";t=b=>b[0].map((x,i)=>b.map(x=>x[i]));i=>{m=i.split`
`;for(h of m){m[m[s](h)]=h.split``;}for(y=0;y<m.length;y++){for(z=x=0;x<m[y].length;x++){if(m[y][x]==h)break;if(m[y][s](h)<x&&m[y][k](h)>x)z++;q=t(m);if(q[y][s]h)<x&&m[y][k](h)>x)z++;if(z>2)m[y][x]=h}}for(p of m){v=p.join``.match(/\S/);e=v?p.join``:'';m[m[s](p)]=e;}m=m.join`
`;return m.replace(#/g," ")}

Si. Lo intenté. Y, aunque estoy en 485 bytes, estoy ganando porque nadie más quería responder a esta pregunta. Entonces, ja!
Y también, soy muy consciente de que podría jugar mucho golf, estoy cansado en este momento ... bueno, ahora estoy en 396 Gracias a Conor por la mayor parte del golf ...: D

Bantha calvo
fuente
1
Declare las variables dentro de los bucles for afuera cony=z=0
Bálint