Remplir une grille 2D

9

Description du défi

Appelons un tableau rectangulaire à deux dimensions (ce qui signifie que chaque sous-tableau a la même longueur), une grille . Chaque unité d'une grille est soit un espace vide, soit une bordure . Dans une grille de caractères, l'espace vide est représenté par un seul espace blanc; tout autre caractère est traité comme une bordure. Exemples de grilles ( +', |' et -'ajoutés pour plus de lisibilité - ils ne font pas partie de la grille ):

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

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

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

Étant donné une grille 2D et une paire de coordonnées, remplissez la zone fermée entourant le point représenté par les coordonnées.

Exemples d'entrées / sorties

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

Remarques

  • Une grille vide est considérée comme fermée, c'est-à-dire que les bordures sont également implicitement situées le long des bords de la grille (voir les exemples 1. et 5.),

  • Un coin d'un espace clos n'a pas besoin d'être en forme de L. Les deux domaines suivants sont donc équivalents:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Si une unité sous les coordonnées se trouve être une bordure, vous pouvez soit laisser la grille inchangée (comme dans l'exemple 4.), soit la traiter comme un espace vide,

  • Vous pouvez choisir n'importe quel caractère pour remplir / espace vide tant que vous incluez ces informations dans la soumission,

  • Si vous utilisez un type autre que celui charqui vous convient mieux, vous pouvez utiliser ints( 0pour un espace vide, 1pour une bordure) ou booleans( trueet falserespectivement) ou tout autre type - assurez-vous simplement d'inclure ces informations dans votre soumission,

  • Les coordonnées utilisées dans les exemples ci-dessus sont des (row, column)coordonnées indexées 0 , car c'est plus pratique pour un tableau à deux dimensions. Si vous souhaitez utiliser un système (column, row)(cartésien) et / ou des coordonnées non indexées 0, spécifiez-le dans votre soumission.

  • Si vous ne savez pas par où commencer, consultez l'article Wikipedia sur le remplissage des inondations

  • N'oubliez pas qu'il s'agit d'un défi de , alors faites votre code aussi court que possible!

shooqie
la source
Connexes: 1 , 2 , 3 , 4 , peut-être plus.
Peter Taylor
Cela pourrait valoir la peine d'avoir un cas de test avec une seule unité de bordure à la position des coordonnées, pour montrer qu'il y a deux sorties valides: soit la grille est entièrement remplie, soit la grille est inchangée. (Si j'ai bien compris votre 3e note.)
trichoplax
Voir ex. 4) Mise à jour
shooqie
1
Je ne comprends pas comment vous obtenez votre autre exemple 4. Cela semble détruire les cellules de bordure autres que le carré d'entrée spécifié.
Joffan

Réponses:

4

MATLAB, 30 7 octets

Comme nous pouvons utiliser des entrées logiques au lieu de chaînes, nous pouvons utiliser la fonction nue, telle qu'elle est:

@imfill

Il s'agit d'une fonction anonyme. Pour l'utilisation, nous devons assumer un nom, par exemple f=@imfill. Ensuite, nous pouvons simplement l'évaluer comme f(input,point), où inputest une matrice logique, par exemple [0,0;0,1], et pointest un vecteur 2d avec des coordonnées basées sur 1, par exemple [1,2].

Ancienne version fonctionnant sur des chaînes:

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

Cette fonction anonyme accepte l'entrée ainsi qu'un vecteur avec les coordonnées (index basé sur 1). La fonction imfillfait exactement ce dont nous avons besoin, mais ne fonctionne que sur les images binaires. C'est pourquoi nous convertissons la matrice d'entrée en un tableau logique (où #sont les frontières et (les espaces) sont le vide), effectue le remplissage et est ensuite reconverti. (encore une fois #est rempli, l'espace n'est pas rempli).

Merci @LuisMendo pour - 1 octet.

flawr
la source
Pour la version chaîne, vous pouvez remplacer ~=32par>32
Luis Mendo
3

C, 162 octets

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);}

Prend l'entrée des arguments ( ./floodfill X Y grid). La grille doit contenir \nou \r\nentre chaque ligne, la nouvelle ligne finale est facultative. Le moyen le plus simple que j'ai trouvé pour invoquer depuis le shell:

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

Sorties vers stdout, en utilisant !pour le caractère de remplissage. Si la position de départ coïncide avec a #, ne change rien.

Panne:

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

Notez que cela repose sur la modification de la chaîne d'argument d'entrée, ce qui est interdit, donc cela peut ne pas fonctionner sur toutes les plateformes (les déclarations implicites rendent également cela non standard).

Dave
la source
Vous pouvez enregistrer 4 octets en changeant int w, l;simplement w, l;- par défaut gcc à inttaper
Jacajack
@Jacajack bon point! Merci
Dave
1

C - 263 247 240 238 octets

Ceci est la première deuxième troisième version, je pense que le code peut également être réduit.

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]);}

Et version lisible:

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] );     

}

Compiler et exécuter:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Ressources:

Remarque: je travaille sur les intvaleurs. Chaque (32) est traité comme un espace vide. Toute autre valeur est traitée comme une bordure. Les coordonnées sont au format(row, column)

Jacajack
la source
1
N'oubliez pas que vous pouvez enregistrer des points-virgules en plaçant des instructions à l'intérieur de for( scanfici), et en utilisant le premier paramètre de main comme déclaration int bon marché fonctionnera dans la plupart des compilateurs. Vous pourriez également être en mesure d'économiser un peu en aplatissant votre tableau (cela devrait certainement aider la boucle d'impression)
Dave
@Dave C'est vrai. J'ai appris un peu depuis que j'ai écrit ce code. Je pense que le stockage de données dans un tableau 1D m'aiderait également à économiser beaucoup, mais je ne veux évidemment pas copier votre idée. Je verrai ce que je peux faire plus tard. Merci!
Jacajack
0

Python 2, 158 octets

Essayez-le en ligne . Solution récursive simple

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

0 indexé dans l'ordre ligne-colonne

1 - espace vide, 0 - espace rempli

Prend l'entrée en tant que tableau de tableaux de 1 et 0 et de deux nombres

Possum mort
la source
0

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

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

Essayez-le en ligne!

Comment?

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
la source