Залейте 2D сетку

9

Описание задачи

Давайте назовем двумерный прямоугольный массив (т.е. каждый его подмассив имеет одинаковую длину) сеткой . Каждая единица сетки - это либо пустое пространство, либо граница . В сетке символов пустое пространство представлено одним пробелом; любой другой символ рассматривается как граница. Примеры таблиц ( для удобства чтения добавлены +«s», |«s» и -« они» - они не являются частью сетки ):

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

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

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

Учитывая двумерную сетку и пару координат, заполните закрытую область, окружающую точку, представленную координатами.

Образцы входов / выходов

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

Ноты

  • Пустая сетка считается вложенной, то есть границы также неявно расположены по краям сетки (см. Примеры 1. и 5.),

  • Угол замкнутого пространства не обязательно должен быть L-образным. Следующие две области, следовательно, эквивалентны:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Если юнит под координатами оказывается границей, вы можете либо оставить сетку без изменений (как в примере 4.), либо рассматривать ее как пустое пространство,

  • Вы можете выбрать любой символ для заполнения / пустого пространства, если вы включите эту информацию в представление,

  • Если вы используете тип, отличный от charваших целей, вы можете использовать ints( 0для пустого пространства, 1для границы) или booleans( trueи falseсоответственно) или любой другой тип - просто убедитесь, что вы включили эту информацию в свое представление,

  • Координаты, используемые в примерах выше, являются 0-индексированными (row, column)координатами, так как это более удобно для двумерного массива. Если вы хотите использовать (column, row)(декартову) систему и / или не-индексированные координаты, укажите это в своем представлении.

  • Если вы не знаете, с чего начать, посмотрите статью в Википедии о заливке

  • Помните, что это вызов, поэтому сделайте ваш код как можно короче!

shooqie
источник
По теме: 1 , 2 , 3 , 4 , возможно, больше.
Питер Тейлор
Возможно, стоит иметь тестовый пример с единичным пограничным блоком в позиции координат, чтобы показать, что есть два допустимых результата: либо сетка полностью заполнена, либо сетка не изменилась. (Если я правильно понял вашу третью ноту.)
trichoplax
См. Бывший 4) обновление
shooqie
1
Я не понимаю, как вы получаете ваш альтернативный пример 4. Кажется, что он уничтожает граничные ячейки, кроме указанного квадрата ввода.
Джоффан

Ответы:

4

MATLAB, 30 7 байтов

Поскольку мы можем использовать логические входы вместо строк, мы можем использовать голую функцию, как она есть:

@imfill

Это анонимная функция. Для использования мы должны принять имя, например f=@imfill. Тогда мы можем просто оценить это как f(input,point), где inputнаходится логическая матрица, например,[0,0;0,1] , и point2d-вектор с основанными на 1 координатами, например [1,2].

Старая версия работает над строками:

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

Эта анонимная функция принимает входные данные, а также вектор с координатами (индекс на основе 1). Функция imfillделает именно то, что нам нужно, но работает только с двоичными изображениями. Вот почему мы конвертируем входную матрицу в логический массив (где# границы, а (пробелы) - пустота), выполняют заполнение и затем преобразуются обратно. (снова #заполнено, пространство не заполнено).

Спасибо @LuisMendo за - 1 байт.

flawr
источник
Для строковой версии вы можете заменить ~=32на>32
Луис Мендо
3

C 162 байта

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

Принимает входные данные от аргументов ( ./floodfill X Y grid). Сетка должна содержать \nили \r\nмежду каждой строкой, окончательный перевод новой строки не является обязательным. Простейший способ, который я нашел для вызова из оболочки:

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

Вывод в стандартный вывод, используя !для заполнения символа. Если начальная позиция совпадает с #, не вносит изменений.

Сломать:

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

Обратите внимание, что это зависит от изменения строки входного аргумента, что запрещено, поэтому это может не работать на всех платформах (неявные объявления также делают это нестандартным).

Дейв
источник
Вы можете сохранить 4 байта, изменяя int w, l;просто w, l;- НКУ по умолчанию это intтип
Jacajack
@ Джакаджек, хорошая мысль! Спасибо
Дейв
1

C - 263 247 240 238 байт

Это первая вторая третья версия, я думаю, что код тоже можно сжать.

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

И читаемая версия:

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

}

Скомпилируйте и запустите:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Ресурсы:

Примечание: я работаю над intценностями. Каждый (32) рассматривается как пустое пространство. Любое другое значение рассматривается как граница. Координаты в формате(row, column)

Jacajack
источник
1
Не забывайте, что вы можете сохранять точки с запятой, помещая операторы внутри for( scanfздесь), и используя первый параметр main как дешевое объявление int, будет работать в большинстве компиляторов. Также вы можете сэкономить, сгладив массив (это, безусловно, должно помочь циклу печати)
Дейв
@ Дейв Это верно. Я немного узнал с тех пор, как написал этот код. Я думаю, что хранение данных в массиве 1D поможет мне сэкономить много, но, очевидно, я не хочу копировать вашу идею. Я посмотрю, что я могу сделать позже. Спасибо!
Jacajack
0

Python 2, 158 байт

Попробуйте онлайн . Простое рекурсивное решение

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 индексируется в порядке строк-столбцов

1 - пустое пространство, 0 - заполненное пространство

Принимает ввод в виде массива массивов 1 и 0 и двух чисел

Мертвый Опоссум
источник
0

Perl 5 , 129 + 1 (-a) = 130 байт

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

Попробуйте онлайн!

Как?

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
источник