Cosa viene circondato


18

Ho sempre voluto circondare un po 'di testo con #s, ma ho difficoltà a capire cosa ho circondato, quindi in questa sfida scriverai un programma per farlo

Esempi

Input / Output sono separati da una nuova riga.

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

Spec

  • #s sono ciò che "circonda" un blocco di testo
  • # sarà sempre adiacente l'uno all'altro (anche in diagonale)
  • # sempre formare una forma chiusa
  • Ci sarà solo una #forma
  • In caso di forma concava, i fori devono essere riempiti di spazi.
  • Gli spazi bianchi devono essere preservati nell'output

all'inizio ero come .. basta prendere le #s e ci si va ... e poi ha ottenuto duro.
Calvo Bantha

Ho problemi a ottenere input in javascript e a dividere per newline ... come devo ottenere input? potrebbe essere formattato con un \ndopo ogni riga di input e passato come parametro param al mio programma o cosa?
Calvo Bantha

1
Qual è l'insieme di caratteri di input validi?
Ton Hospel,

C'è un errore nell'output dell'esempio MN ? Il suo output è costituito solo dal testo racchiuso _M_\n___N(utilizzando i trattini bassi anziché gli spazi a causa di problemi di formattazione), mentre negli esempi abc e Codego l'output include anche spazi bianchi in cui # erano nell'input. Se deve essere stampato solo il testo racchiuso tra #s, l'output dell'esempio abc dovrebbe essere _a_\n_b_c_(anziché __a_\n_b_c) e l'output dell'esempio Codego dovrebbe essere Co\nde\n_go(anziché C___o\nd___e\n__go).
epidemia

@epidemian ah, bella cattura. Ho fissato l' MNesempio. come non di ci dovrebbe essere uno spazio in più dopo M.
Downgoat

Risposte:


6

Perl, 144 138 132 129 128 127 126 124 byte

Include +2 per -p0

Il codice presuppone \0non è un carattere di input valido (almeno all'interno #).

Eseguire con l'ingresso sul 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;#; 

Il codice funziona così com'è, ma sostituisce \0e \ncon le loro versioni letterali per il punteggio richiesto. Si noti che c'è uno spazio alla fine della linea. Il codice scorre un numero eccessivo di volte, quindi potrebbe essere necessario attendere circa 30 secondi per l'output.

Spiegazione

Farò un'alluvione con \0fermata #dall'esterno nelle direzioni ortogonali. Dopodiché taglierò i #lati e sostituirò tutto ciò che rimane degli spazi. Per evitare di dover gestire tutte le direzioni nell'alluvione, ruoterò ripetutamente l'area target e solo l'inondazione da destra a sinistra

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

A questo punto ad es

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

sarà stato sostituito da:

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

Fondamentalmente tutte le colonne e le righe che non sono direttamente confinanti con l'interno sono state tagliate. Tutti i caratteri esterni rimasti sono stati sostituiti da \ 0. In alto ea destra c'è un ulteriore livello di \ 0. Quindi tutto ciò che rimane è la pulizia:

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

I vostri floodfills aggirare angoli interni, se ci fossero?
mbomb007

@ mbomb007: Sì, poiché l'area viene ripetutamente ruotata, quindi è in grado di seguire tutti i corridoi tortuosi. Il loop che si interrompe troppo presto prima di ridurre muri molto spessi è l'unico difetto per quanto ne so
Ton Hospel

@ mbomb007: Aaaa e il grosso difetto del muro è ora risolto
Ton Hospel

copiando e incollando la soluzione così com'è (non sostituendo i caratteri di escape), l'output è semplicemente l'input con tutto #eliminato. per favore verifica la mia sessione bash: codepad.org/YbCzB4O4
ardnew,

@ardnew: Oops, scusa. Per l'ultimo aggiornamento non ho riproposto la soluzione completa e avrei dovuto sostituire il tempo con un fino a. Risolto ora, per favore riprova
Ton Hospel,

4

Javascript, 485 464 427 417 396 390 byte

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," ")}

Sì. Provai. E, anche se sono a 485 byte, sto vincendo perché nessun altro ha voglia di rispondere a questa domanda. Quindi ah!
E inoltre, sono ben consapevole di poter giocare a golf così tanto, sono solo stanco al momento ... beh, ora sono a 396 grazie a Conor per la maggior parte del golf ...: D


1
Dichiarare le variabili all'interno di per i cicli all'esterno cony=z=0
Bálint,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.