Lấp đầy lưới 2D


9

Mô tả thử thách

Chúng ta hãy gọi một mảng hai chiều, hình chữ nhật (có nghĩa là mọi phân đoạn của nó có cùng độ dài), một lưới . Mỗi đơn vị của lưới là một không gian trống hoặc một đường viền . Trong một lưới các ký tự, không gian trống được biểu thị bằng một khoảng trắng duy nhất; bất kỳ nhân vật khác được coi là một biên giới. Lưới mẫu ( +'s, |' s và -'s gia tăng đối với khả năng đọc - chúng không phải là một phần của lưới điện ):

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

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

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

Cho một lưới 2D và một cặp tọa độ, điền vào vùng kín xung quanh điểm được biểu thị bằng tọa độ.

Đầu vào / đầu ra mẫu

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

Ghi chú

  • Một lưới trống được coi là kèm theo, tức là các đường viền được đặt hoàn toàn dọc theo các cạnh của lưới (xem ví dụ 1. và 5.),

  • Một góc của một khu vực kín không cần phải có hình chữ L. Hai lĩnh vực sau đây là tương đương nhau:

####         ##
#  #        #  #
#  #   ==   #  #
#  #        #  #
####         ##
  • Nếu một đơn vị dưới tọa độ xảy ra là một đường viền, bạn có thể giữ lưới không thay đổi (như trong ví dụ 4.) hoặc coi nó là một khoảng trống,

  • Bạn có thể chọn bất kỳ ký tự nào cho filler / khoảng trống miễn là bạn bao gồm thông tin này trong bài gửi,

  • Nếu sử dụng một loại khác không charphù hợp với mục đích của bạn hơn, bạn có thể sử dụng ints( 0cho không gian trống, 1cho đường viền) hoặc booleans( truefalsetương ứng) hoặc bất kỳ loại nào khác - chỉ cần đảm bảo đưa thông tin này vào trình của bạn,

  • Các tọa độ được sử dụng trong các ví dụ ở trên là (row, column)tọa độ 0 được lập chỉ mục , vì nó thuận tiện hơn cho mảng hai chiều. Nếu bạn muốn sử dụng (column, row)hệ thống (cartesian) và / hoặc tọa độ không có chỉ số 0, hãy chỉ định nó trong bài gửi của bạn.

  • Nếu bạn không biết bắt đầu từ đâu, hãy xem bài viết trên Wikipedia về lũ lụt

  • Hãy nhớ rằng đây là một thử thách , vì vậy hãy viết mã của bạn càng ngắn càng tốt!


Liên quan: 1 , 2 , 3 , 4 , có thể nhiều hơn nữa.
Peter Taylor

Có thể đáng để có một trường hợp thử nghiệm với một đơn vị đường viền duy nhất ở vị trí tọa độ, để cho thấy rằng có hai đầu ra hợp lệ: Hoặc là lưới được lấp đầy hoặc lưới không thay đổi. (Nếu tôi đã hiểu chính xác ghi chú thứ 3 của bạn.)
trichoplax

Xem người cũ 4) cập nhật
shooqie

1
Tôi không hiểu làm thế nào bạn có được ví dụ thay thế 4. Điều đó dường như đang phá hủy các ô viền khác với ô vuông đầu vào được chỉ định.
Joffan

Câu trả lời:


4

MATLAB, 30 7 byte

Vì chúng ta có thể sử dụng các đầu vào logic thay vì các chuỗi, chúng ta có thể sử dụng hàm trần, vì nó là:

@imfill

Đây là một chức năng ẩn danh. Đối với việc sử dụng, chúng ta phải giả sử một tên, ví dụ f=@imfill. Sau đó, chúng tôi chỉ có thể đánh giá nó như là f(input,point), nơi inputlà một ma trận hợp lý, ví dụ [0,0;0,1], và pointlà một 2ngày vector có tọa độ 1 có trụ sở, ví dụ [1,2].

Phiên bản cũ hoạt động trên chuỗi:

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

Hàm ẩn danh này chấp nhận đầu vào cũng như một vectơ với tọa độ (chỉ mục dựa trên 1). Hàm imfillnày thực hiện chính xác những gì chúng ta cần, nhưng chỉ hoạt động trên hình ảnh nhị phân. Đó là lý do tại sao chúng tôi chuyển đổi ma trận đầu vào thành một mảng logic (trong đó #các ranh giới và (khoảng trắng) là khoảng trống), thực hiện điền và sau đó được chuyển đổi trở lại. (một lần nữa #được lấp đầy, không gian không được lấp đầy).

Cảm ơn @LuisMendo cho - 1 byte.


Đối với phiên bản chuỗi, bạn có thể thay thế ~=32bằng>32
Luis Mendo

3

C, 162 byte

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

Lấy đầu vào từ đối số ( ./floodfill X Y grid). Lưới phải chứa \nhoặc \r\ngiữa mỗi dòng, dòng mới cuối cùng là tùy chọn. Cách đơn giản nhất mà tôi đã tìm thấy để gọi từ shell:

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

Đầu ra cho thiết bị xuất chuẩn, sử dụng !cho ký tự điền. Nếu vị trí bắt đầu trùng với a #, không thay đổi.

Phá vỡ:

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

Lưu ý rằng điều này phụ thuộc vào việc sửa đổi chuỗi đối số đầu vào bị cấm, do đó, điều này có thể không hoạt động trên tất cả các nền tảng (khai báo ngầm cũng làm cho điều này không chuẩn).


Bạn có thể lưu 4 byte bằng cách thay đổi int w, l;thành đơn giản w, l;- gcc mặc định nó để int
Jacajack

@Jacajack điểm tốt! Cảm ơn
Dave

1

C - 263 247 240 238 byte

Đây là phiên bản thứ ba thứ hai đầu tiên , tôi tin rằng mã cũng có thể được thu nhỏ.

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

Và phiên bản có thể đọc được:

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

}

Biên dịch và chạy:
gcc -o flood floodgolf.c && cat 1.txt | ./flood

Tài nguyên:

Lưu ý: Tôi đang làm việc trên intcác giá trị. Mỗi (32) được coi là không gian trống. Bất kỳ giá trị khác được coi là biên giới. Các tọa độ có định dạng(row, column)


1
Đừng quên bạn có thể lưu dấu chấm phẩy bằng cách đặt các câu lệnh bên trong for( scanfở đây) và sử dụng tham số đầu tiên của main làm khai báo int giá rẻ sẽ hoạt động trong hầu hết các trình biên dịch. Ngoài ra, bạn có thể tiết kiệm được một chút bằng cách làm phẳng mảng của mình (chắc chắn sẽ giúp vòng lặp in)
Dave

@Dave Đúng vậy. Tôi đã học được một chút kể từ khi tôi viết mã này. Tôi nghĩ việc lưu trữ dữ liệu trong mảng 1D cũng sẽ giúp tôi tiết kiệm rất nhiều, nhưng rõ ràng tôi không muốn sao chép ý tưởng của bạn. Tôi sẽ xem những gì tôi có thể làm sau này. Cảm ơn!
Jacajack

0

Python 2, 158 byte

Hãy thử trực tuyến . Giải pháp đệ quy đơn giản

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 - được lập chỉ mục theo thứ tự cột hàng

1 - không gian trống, 0 - không gian đầy

Lấy đầu vào là mảng các mảng 1 và 0 và hai số


0

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

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

Hãy thử trực tuyến!

Làm sao?

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.