Wypełnij powódź siatką 2D


9

Opis wyzwania

Nazwijmy dwuwymiarową prostokątną tablicę (co oznacza, że ​​każda podtablica ma tę samą długość), siatkę . Każda jednostka siatki jest pustą przestrzenią lub ramką . W siatce znaków puste miejsce jest reprezentowane przez pojedynczą białą spację; każdy inny znak jest traktowany jak obramowanie. Przykładowe Siatki ( +„s, |” s i -s dodaną”dla czytelności - nie są one częścią sieci ):

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

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

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

Biorąc pod uwagę siatkę 2D i parę współrzędnych, wypełnij zamknięty obszar otaczający punkt reprezentowany przez współrzędne.

Przykładowe wejścia / wyjścia

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

Notatki

  • Pusta siatka jest uważana za zamkniętą, tzn. Granice są również domyślnie umieszczone wzdłuż krawędzi siatki (patrz przykłady 1. i 5.),

  • Narożnik zamkniętego obszaru nie musi mieć kształtu litery L. Następujące dwa obszary są zatem równoważne:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Jeśli jednostka pod współrzędnymi stanie się ramką, możesz pozostawić siatkę bez zmian (jak w przykładzie 4) lub potraktować ją jako puste miejsce,

  • Możesz wybrać dowolny znak do wypełnienia / pustej przestrzeni, o ile podasz te informacje w formularzu

  • Jeśli używasz innego typu niż charnajlepiej pasuje do twoich celów, możesz użyć ints( 0dla pustej przestrzeni, 1dla obramowania) lub booleans( truei falseodpowiednio) lub dowolnego innego typu - pamiętaj tylko o umieszczeniu tych informacji w swoim zgłoszeniu,

  • Współrzędne użyte w powyższych przykładach są (row, column)współrzędnymi 0-indeksowanymi , ponieważ jest to wygodniejsze w przypadku układu dwuwymiarowego. Jeśli chcesz użyć (column, row)(kartezjańskiego) układu i / lub współrzędnych nieindeksowanych, podaj go w swoim zgłoszeniu.

  • Jeśli nie wiesz, od czego zacząć, zapoznaj się z artykułem Wikipedii na temat wypełniania powodzi

  • Pamiętaj, że to jest wyzwanie, więc ustaw swój kod tak krótko, jak to możliwe!


Powiązane: 1 , 2 , 3 , 4 , ewentualnie więcej.
Peter Taylor,

Warto mieć przypadek testowy z pojedynczą jednostką graniczną w pozycji współrzędnych, aby pokazać, że istnieją dwa prawidłowe dane wyjściowe: Albo siatka jest całkowicie wypełniona, albo siatka pozostaje niezmieniona. (Jeśli poprawnie zrozumiałem twoją trzecią notatkę.)
trichoplax

Zobacz np. 4) aktualizacja
shooqie,

1
Nie rozumiem, w jaki sposób otrzymujesz alternatywny przykład 4. Wygląda na to, że niszczy komórki graniczne inne niż określony kwadrat wejściowy.
Joffan

Odpowiedzi:


4

MATLAB, 30 7 bajtów

Ponieważ zamiast ciągów znaków możemy używać logicznych danych wejściowych, możemy używać samej funkcji, ponieważ jest to:

@imfill

To anonimowa funkcja. W celu użycia musimy przyjąć nazwę, np f=@imfill. Następnie możemy to po prostu ocenić jako f(input,point), gdzie input, na przykład [0,0;0,1], pointjest macierzą logiczną i jest wektorem 2d ze współrzędnymi opartymi na 1, np [1,2].

Stara wersja działająca na ciągach:

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

Ta anonimowa funkcja przyjmuje dane wejściowe oraz wektor ze współrzędnymi (indeks oparty na 1). Funkcja imfillrobi dokładnie to, czego potrzebujemy, ale działa tylko na obrazach binarnych. Dlatego konwertujemy macierz wejściową na tablicę logiczną (gdzie #są granice, a (spacje) są puste), wykonuje wypełnienie, a następnie jest konwertowane z powrotem. (ponownie #jest wypełniony, przestrzeń nie jest wypełniona).

Dzięki @LuisMendo za - 1 bajt.


Dla wersji strun, można zastąpić ~=32przez>32
Luis Mendo

3

C, 162 bajty

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

Pobiera dane wejściowe z argumentów ( ./floodfill X Y grid). Siatka musi zawierać \nlub \r\npomiędzy każdą linię, końcowa nowa linia jest opcjonalna. Najprostszy sposób na wywołanie z powłoki:

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

Wyprowadza na standardowe wyjście, używając !znaku wypełnienia. Jeśli pozycja początkowa pokrywa się z a #, nie zmienia.

Awaria:

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

Zauważ, że polega to na modyfikacji wejściowego ciągu argumentów, co jest zabronione, więc może nie działać na wszystkich platformach (deklaracje niejawne również powodują, że jest to niestandardowe).


Można zapisać 4 bajty zmieniając int w, l;po prostu w, l;- domyślnie gcc go intwpisać
Jacajack

@Jacajack dobry punkt! Dzięki
Dave

1

C - 263 247 240 238 bajtów

To jest pierwsza druga trzecia wersja, uważam, że kod można również zmniejszyć.

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

I czytelna wersja:

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

}

Skompiluj i uruchom:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Zasoby:

Uwaga: pracuję nad intwartościami. Każdy (32) jest traktowany jako puste miejsce. Każda inna wartość jest traktowana jako granica. Współrzędne są w formacie(row, column)


1
Nie zapominaj, że możesz zapisać średniki, wstawiając instrukcje do for( scanftutaj), a użycie pierwszego parametru main jako taniej deklaracji int będzie działać w większości kompilatorów. Możesz także być w stanie zaoszczędzić trochę, spłaszczając tablicę (powinno to z pewnością pomóc w pętli drukowania)
Dave

@Dave Zgadza się. Nauczyłem się trochę odkąd napisałem ten kod. Myślę, że przechowywanie danych w macierzy 1D pomogłoby mi również dużo zaoszczędzić, ale oczywiście nie chcę kopiować twojego pomysłu. Zobaczę, co mogę zrobić później. Dzięki!
Jacajack

0

Python 2, 158 bajtów

Wypróbuj online . Proste rozwiązanie rekurencyjne

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-indeksowane w kolejności wiersz-kolumna

1 - puste miejsce, 0 - wypełnione miejsce

Pobiera dane wejściowe jako tablicę tablic 1 i 0 oraz dwie liczby


0

Perl 5 , 129 + 1 (-a) = 130 bajtów

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

Wypróbuj online!

W jaki sposób?

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.