Füllen Sie ein 2D-Gitter mit Flut

9

Beschreibung der Herausforderung

Nennen wir ein zweidimensionales, rechteckiges Array (dh jedes Subarray hat die gleiche Länge), ein Raster . Jede Einheit eines Gitters ist entweder ein leerer Raum oder ein Rand . In einem Zeichenraster wird der leere Raum durch ein einzelnes Leerzeichen dargestellt. Jedes andere Zeichen wird als Rahmen behandelt. Beispielgitter ( +'s, |' s und -'s wurden zur besseren Lesbarkeit hinzugefügt - sie sind nicht Teil des Gitters ):

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

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

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

Füllen Sie bei einem 2D-Raster und einem Koordinatenpaar den umschlossenen Bereich um den durch die Koordinaten dargestellten Punkt.

Beispiel Ein- / Ausgänge

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

Anmerkungen

  • Ein leeres Gitter wird als eingeschlossen betrachtet, dh die Ränder befinden sich implizit auch entlang der Ränder des Gitters (siehe Beispiele 1. und 5.).

  • Eine Ecke eines geschlossenen Bereichs muss nicht L-förmig sein. Die folgenden zwei Bereiche sind daher gleichwertig:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Wenn eine Einheit unter den Koordinaten zufällig ein Rand ist, können Sie das Raster entweder unverändert lassen (wie in Beispiel 4.) oder es als leeren Raum behandeln.

  • Sie können ein beliebiges Zeichen für Füll- / Leerzeichen auswählen, solange Sie diese Informationen in die Übermittlung aufnehmen.

  • Bei Verwendung einen anderen Typ als charIhre Zwecke besser paßt, die Sie verwenden können ints( 0für leeren Raum, 1für Grenz) oder booleans( trueund falsejeweils) oder jede andere Art - nur sicherstellen , dass diese Informationen in Ihrer Vorlage schließen,

  • Die in den obigen Beispielen verwendeten Koordinaten sind 0-indizierte (row, column)Koordinaten, da dies für zweidimensionale Arrays bequemer ist. Wenn Sie ein (column, row)(kartesisches) System und / oder nicht 0-indizierte Koordinaten verwenden möchten , geben Sie dies in Ihrer Einreichung an.

  • Wenn Sie nicht wissen, wo Sie anfangen sollen, lesen Sie den Wikipedia-Artikel über Hochwasserfüllung

  • Denken Sie daran, dass dies eine Herausforderung ist. Machen Sie Ihren Code so kurz wie möglich!

shooqie
quelle
Verwandte: 1 , 2 , 3 , 4 , möglicherweise mehr.
Peter Taylor
Es könnte sich lohnen, einen Testfall mit einer einzelnen Randeinheit an der Position der Koordinaten zu haben, um zu zeigen, dass es zwei gültige Ausgaben gibt: Entweder ist das Gitter vollständig gefüllt oder das Gitter ist unverändert. (Wenn ich Ihre 3. Note richtig verstanden habe.)
Trichoplax
Siehe ex. 4) Update
Shooqie
1
Ich verstehe nicht, wie Sie Ihr alternatives Beispiel 4 erhalten. Das scheint andere Randzellen als das angegebene Eingabequadrat zu zerstören.
Joffan

Antworten:

4

MATLAB, 30 7 Bytes

Da wir anstelle von Zeichenfolgen logische Eingaben verwenden können, können wir die Bare-Funktion wie folgt verwenden:

@imfill

Dies ist eine anonyme Funktion. Für die Verwendung müssen wir einen Namen annehmen, z f=@imfill. Dann können wir bewerten es ebenso f(input,point), wo inputeine logische Matrix ist, zum Beispiel [0,0;0,1], und pointist ein 2D-Vektor mit 1 basierten Koordinaten, zum Beispiel [1,2].

Alte Version, die an Strings arbeitet:

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

Diese anonyme Funktion akzeptiert die Eingabe sowie einen Vektor mit den Koordinaten (1-basierter Index). Die Funktion imfillmacht genau das, was wir brauchen, arbeitet aber nur mit Binärbildern. Deshalb konvertieren wir die Eingabematrix in ein logisches Array (wo #sind die Grenzen und (Leerzeichen) sind die Leere), führen die Füllung durch und werden dann zurück konvertiert. (wieder #ist gefüllt, Raum ist nicht gefüllt).

Danke @LuisMendo für - 1 Byte.

fehlerhaft
quelle
Für die String-Version können Sie ~=32durch>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);}

Nimmt Eingaben von Argumenten ( ./floodfill X Y grid) entgegen. Das Raster muss \noder \r\nzwischen jeder Zeile enthalten, die letzte neue Zeile ist optional. Der einfachste Weg, den ich gefunden habe, um von der Shell aus aufzurufen:

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

Ausgaben an stdout unter Verwendung !des Füllzeichens. Wenn die Startposition mit a übereinstimmt #, ändert sich nichts.

Nervenzusammenbruch:

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

Beachten Sie, dass dies auf dem Ändern der verbotenen Eingabeargumentzeichenfolge beruht, sodass dies möglicherweise nicht auf allen Plattformen funktioniert (implizite Deklarationen machen dies ebenfalls nicht zum Standard).

Dave
quelle
Sie können 4 Bytes speichern , indem int w, l;einfach w, l;- gcc defaults es zu intgeben
Jacajack
@ Jacajack guter Punkt! Vielen Dank
Dave
1

C - 263 247 240 238 Bytes

Dies ist die erste, zweite und dritte Version. Ich glaube, Code kann auch verkleinert werden.

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

Und lesbare Version:

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

}

Kompilieren und ausführen:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Ressourcen:

Hinweis: Ich arbeite an intWerten. Jedes (32) wird als leerer Raum behandelt. Jeder andere Wert wird als Rand behandelt. Koordinaten sind im Format(row, column)

Jacajack
quelle
1
Vergessen Sie nicht, dass Sie Semikolons speichern können, indem Sie Anweisungen in for( scanfhier) einfügen. Die Verwendung des ersten Parameters von main als billige int-Deklaration funktioniert in den meisten Compilern. Außerdem können Sie möglicherweise ein wenig sparen, indem Sie Ihr Array reduzieren (sollte sicherlich der Druckschleife helfen)
Dave
@ Dave Das stimmt. Ich habe ein bisschen gelernt, seit ich diesen Code geschrieben habe. Ich denke, das Speichern von Daten in einem 1D-Array würde mir auch helfen, viel zu sparen, aber natürlich möchte ich Ihre Idee nicht kopieren. Ich werde später sehen, was ich tun kann. Vielen Dank!
Jacajack
0

Python 2, 158 Bytes

Probieren Sie es online aus . Einfache rekursive Lösung

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-indiziert in Zeilen-Spalten-Reihenfolge

1 - leerer Raum, 0 - gefüllter Raum

Übernimmt die Eingabe als Array von Arrays mit 1 und 0 sowie zwei Zahlen

Totes Opossum
quelle
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

Probieren Sie es online aus!

Wie?

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
quelle