Preencha uma grade 2D

9

Descrição do Desafio

Vamos chamar uma matriz retangular bidimensional (ou seja, cada subarray tem o mesmo comprimento), uma grade . Cada unidade de uma grade é um espaço vazio ou uma borda . Em uma grade de caracteres, o espaço vazio é representado por um único espaço em branco; qualquer outro caractere é tratado como uma borda. Grelhas de amostra ( +', |' e -'adicionadas para facilitar a leitura - elas não fazem parte da grade ):

+----+
|    |
|    |
|    |
|    |
|    |
+----+  an empty 4x5 grid

+------+
|      |
|  #   |
|  #   |
+------+  a 6x3 grid with 2 borders

+----------+
|          |
|          |
|  #####   |
|  #   #   |
| ##   # <------ enclosed area
| #    #   |
| ######   |
|          |
+----------+  a 10x8 grid with an enclosed area

Dada uma grade 2D e um par de coordenadas, preencha a área fechada ao redor do ponto representado pelas coordenadas.

Amostras de entradas / saídas

1)

0 0
+----------+      +----------+
|          |      |XXXXXXXXXX|
|          |  ->  |XXXXXXXXXX|
|          |      |XXXXXXXXXX|
+----------+      +----------+

2)

6 5
+-----------------+      +-----------------+
|                 |      |                 |
|                 |      |                 |
|    ########     |      |    ########     |
|    #       #    |      |    #XXXXXXX#    |
|    #    ####    |      |    #XXXX####    |
|    #    #       |      |    #XXXX#       |
|    #    #       |  ->  |    #XXXX#       |
|    #    #       |      |    #XXXX#       |
|     ####        |      |     ####        |
|                 |      |                 |
|                 |      |                 |
+-----------------+      +-----------------+

3)

4 6
+-----------------+      +-----------------+
|                 |      |XXXXXXXXXXXXXXXXX|
|    ####         |      |XXXX####XXXXXXXXX|
|   #    #        |  ->  |XXX#    #XXXXXXXX|
|    ####         |      |XXXX####XXXXXXXXX|
|                 |      |XXXXXXXXXXXXXXXXX|
+-----------------+      +-----------------+

4)

4 5
+-----------------+      +-----------------+      +-----------------+ 
|                 |      |                 |      |                 |
|                 |      |                 |      |                 |
|    ####         |      |    ####         |      |     XXXX        |
|    ####         |  ->  |    ####         |  or  |     XXXX        |
|    ####         |      |    ####         |      |     XXXX        |
|                 |      |                 |      |                 |
+-----------------+      +-----------------+      +-----------------+

5)

2 6
+----------------+      +----------------+
|                |      |XXXXXXXXXXXXXXXX|
|                |      |XXXXXXXXXXXXXXXX|
|                |      |XXXXXXXXXXXXXXXX|
|                |  ->  |XXXXXXXXXXXXXXXX|
|                |      |XXXXXXXXXXXXXXXX|
|BBBBBBBBBBBBBBBB|      |BBBBBBBBBBBBBBBB|
|                |      |                |
|                |      |                |
+----------------+      +----------------+

Notas

  • Uma grade vazia é considerada fechada, ou seja, as bordas também estão localizadas implicitamente ao longo das bordas da grade (ver exemplos 1. e 5.),

  • Um canto de uma área fechada não precisa ser em forma de L. As duas áreas a seguir são, portanto, equivalentes:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Se uma unidade sob as coordenadas for uma borda, você poderá deixar a grade inalterada (como no exemplo 4.) ou tratá-la como um espaço vazio,

  • Você pode escolher qualquer caractere para preenchimento / espaço vazio, desde que inclua essas informações no envio,

  • Se o uso de um tipo que não seja mais charadequado aos seus objetivos, você poderá usar ints( 0para espaço vazio, 1para borda) ou booleans( truee falserespectivamente) ou qualquer outro tipo - apenas inclua essas informações em seu envio,

  • As coordenadas usadas nos exemplos acima são (row, column)coordenadas com índice 0 , pois é mais conveniente para uma matriz bidimensional. Se você deseja usar o (column, row)sistema (cartesiano) e / ou coordenadas não indexadas a 0, especifique-o no seu envio.

  • Se você não sabe por onde começar, consulte o artigo da Wikipedia sobre preenchimento de inundação

  • Lembre-se de que este é um desafio do , portanto, faça o seu código o mais curto possível!

shooqie
fonte
Relacionados: 1 , 2 , 3 , 4 , possivelmente mais.
Peter Taylor
Pode valer a pena ter um caso de teste com uma única unidade de borda na posição das coordenadas, para mostrar que existem duas saídas válidas: A grade está toda preenchida ou a grade não é alterada. (Se eu entendi a sua 3ª nota corretamente.)
Trichoplax
Veja ex. 4) update
shooqie
11
Não entendo como você obtém seu exemplo alternativo 4. Parece que está destruindo células de borda que não sejam o quadrado de entrada especificado.
Joffan

Respostas:

4

MATLAB, 30 7 bytes

Como podemos usar entradas lógicas em vez de strings, podemos usar a função bare, como é:

@imfill

Esta é uma função anônima. Para o uso, temos que assumir um nome, por exemplo f=@imfill. Então podemos apenas avaliar como f(input,point), onde inputé uma matriz lógica, por exemplo [0,0;0,1], e pointé um vetor 2d com coordenadas baseadas em 1, por exemplo [1,2].

Versão antiga trabalhando em strings:

@(a,p)[imfill(a>32,p)*3+32,'']

Esta função anônima aceita a entrada e também um vetor com as coordenadas (índice baseado em 1). A função imfillfaz exatamente o que precisamos, mas opera apenas em imagens binárias. É por isso que convertemos a matriz de entrada em uma matriz lógica (onde #estão os limites e (os espaços) são nulos), executamos o preenchimento e depois convertemos de volta. (novamente #é preenchido, o espaço não é preenchido).

Obrigado @LuisMendo por - 1 byte.

flawr
fonte
Para a versão em cadeia, você pode substituir ~=32por>32
Luis Mendo
3

C, 162 bytes

w,l;char*d;f(z){z<0||z>l||d[z]^32||++d[z]&&f(z+1)+f(z-1)+f(z+w)+f(z-w);}main(c,v)char**v;{l=strlen(d=v[3]),w=strchr(d,10)-d+1,f(atoi(v[2])*w+atoi(v[1]));puts(d);}

Recebe entrada de argumentos ( ./floodfill X Y grid). A grade deve conter \nou \r\nentre cada linha, a nova linha final é opcional. Maneira mais simples que eu encontrei para invocar a partir do shell:

./floodfill 1 0 "$(printf "   \n###\n   \n")"
# or
./floodfill 1 0 "$(cat gridfile)"

Saídas para stdout, usando !o caractere de preenchimento. Se a posição inicial coincidir com a #, não fará alterações.

Demolir:

                                    // GCC is happy enough without any imports
w,l;                                // Globals (line width, total length)
char*d;                             // Global grid pointer
f(z){                               // "Fill" function - z=current cell
    z<0||z>l||                      // Check if out-of-bounds...
    d[z]^32||                       // ...or not empty
        ++d[z]&&                    // Fill cell...
        f(z+1)+f(z-1)+f(z+w)+f(z-w);// ...and continue in "+" pattern
}
main(c,v)char**v;{                  // K&R style function to save 2 bytes
    l=strlen(d=v[3]),               // Store grid & length
    w=strchr(d,10)-d+1,             // Store width of grid (including newlines)
    f(atoi(v[2])*w+atoi(v[1]));     // Parse X & Y arguments and invoke fill

    puts(d);}                       // Print the result

Observe que isso depende da modificação da sequência de argumentos de entrada, que é proibida, portanto, isso pode não funcionar em todas as plataformas (declarações implícitas também tornam isso não-padrão).

Dave
fonte
Você pode salvar 4 bytes, alterando int w, l;simplesmente w, l;- defaults gcc-lo para intdigitar
Jacajack
@Jacajack good point! Obrigado
Dave
1

C - 263 247 240 238 bytes

Esta é primeira segunda terceira versão, eu acredito que o código pode ser shrinked também.

m[99][99],x,y,a,b,c,n;f(v,w){if(m[v][w]==32){m[v][w]=88;f(v,w+1);f(v+1,w);f(v,w-1);f(v-1,w);}}main(){scanf("%d %d\n",&a,&b);for(;~(c=getchar());m[x++][y]=c,n=x>n?x:n)c==10&&++y&&(x=0);f(b+2,a+1);for(a=-1;++a<y*n+n;)putchar(m[a%n][a/n]);}

E versão legível:

m[99][99], x, y, a, b, c, n;

/*
    a, b - flood fill start coordinates
    v, w - recursive function start coordinates
    x, y - iterators
    c - character read
    m - map
    n - maximum map width found

*/


//Recursive flood function
f( v, w )
{
    if ( m[v][w] == 32 ) //If field is empty (is ' '?)
    {
        m[v][w] = 88; //Put 'X' there
        f(v,w+1);f(v+1,w); //Call itself on neighbour fields
        f(v,w-1);f(v-1,w);
    }
}

main( )
{
    //Read coordinates
    scanf( "%d %d\n", &a, &b );

    //Read map (put character in map, track maximum width)
    for ( ; ~( c = getchar( ) ); m[x++][y] = c, n = x > n ? x : n )
        c == 10 && ++y && ( x = 0 );

    //Flood map
    f( b + 2, a + 1 );

    //Draw
    for ( a = -1; ++a < y * n + n; )
            putchar( m[a % n][a / n] );     

}

Compile e execute:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Recursos:

Nota: estou trabalhando em intvalores. Cada (32) é tratado como espaço vazio. Qualquer outro valor é tratado como borda. As coordenadas estão no formato(row, column)

Jacajack
fonte
11
Não esqueça que você pode salvar ponto-e-vírgula colocando instruções dentro de for( scanfaqui), e usar o primeiro parâmetro de main como uma declaração int barata funcionará na maioria dos compiladores. Além disso, você pode ser capaz de guardar um pouco por achatamento sua matriz (certamente deve ajudar o ciclo de impressão)
Dave
@ Dave Isso mesmo. Eu aprendi um pouco desde que escrevi esse código. Acho que armazenar dados no array 1D também me ajudaria a economizar muito, mas obviamente não quero copiar sua ideia. Verei o que posso fazer mais tarde. Obrigado!
Jacajack
0

Python 2, 158 bytes

Experimente online . Solução recursiva simples

a,X,Y=input()
M=len(a)
N=len(a[0])
def R(x,y):
 if~0<x<M and~0<y<N and a[x][y]:a[x][y]=0;R(x-1,y);R(x+1,y);R(x,y-1);R(x,y+1)
R(X,Y)
print'\n'.join(map(str,a))

Indexado a 0 em ordem de coluna de linha

1 - espaço vazio, 0 - espaço preenchido

Recebe entrada como matriz de matrizes de 1 e 0 e dois números

Gambá morto
fonte
0

Perl 5 , 129 + 1 (-a) = 130 bytes

sub f{my($r,$c)=@_;$a[$r][$c]eq$"&&($a[$r][$c]=X)&&map{f($r+$_,$c);f($r,$c+$_)}-1,1}@a=map[/./g],<>;f$F[0]+1,$F[1]+1;say@$_ for@a

Experimente online!

Como?

sub f{   # recursive subroutine
  my($r,$c)=@_; # taking row and column as inputs
  $a[$r][$c]eq$"&&  # using Boolean short circuit as an 'if' statement to 
                    # check if the current position in the global array is blank
  ($a[$r][$c]=X)&&  # then setting it to 'X'
  map{f($r+$_,$c);f($r,$c+$_)}-1,1 # and checking the four surrounding spaces
}
# -a command line option implicitly splits the first line into the @F array
@a=map[/./g],<>;    # put the input in a 2-D array
f$F[0]+1,$F[1]+1;   # start the fill at the given position, correcting for
                    # Perl's 0 based arrays
say@$_ for@a        # output the resulting pattern
Xcali
fonte