เติมน้ำท่วมกริด 2D


9

คำอธิบายการท้าทาย

ขอเรียกสองมิติอาร์เรย์สี่เหลี่ยม (หมายถึงทุก subarray ของมันมีความยาวเดียวกัน) ซึ่งเป็นตาราง หน่วยของตารางทุกคนเป็นทั้งพื้นที่ว่างหรือชายแดน ในตารางของอักขระพื้นที่ว่างจะถูกแทนด้วยช่องว่างเดียว อักขระอื่นใดถือเป็นเส้นขอบ ตัวอย่างกริด ( +'s, |' s และ-'s เพิ่มเพื่อให้อ่านได้ - มันไม่ได้เป็นส่วนหนึ่งของกริด ):

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

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

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

ให้ตาราง 2D และพิกัดหนึ่งคู่เติมพื้นที่ล้อมรอบจุดที่แสดงโดยพิกัด

ตัวอย่างอินพุต / เอาท์พุต

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ตามลำดับ) หรือประเภทอื่น ๆ - เพียงตรวจสอบให้แน่ใจว่าได้รวมข้อมูลนี้ไว้ในการส่งของคุณแล้ว

  • พิกัดที่ใช้ในตัวอย่างด้านบนเป็น(row, column)พิกัด0 ที่จัดทำดัชนีเนื่องจากสะดวกกว่าสำหรับอาร์เรย์สองมิติ หากคุณต้องการใช้ระบบ(column, row)(คาร์ทีเซียน) และ / หรือพิกัดที่ไม่ใช่ดัชนี 0 ให้ระบุในการส่งของคุณ

  • หากคุณไม่ทราบว่าจะเริ่มจากที่ใดลองอ่านบทความ Wikipedia เกี่ยวกับการเติมน้ำท่วม

  • จำไว้ว่านี่คือ ท้าทายทำรหัสของคุณให้สั้นที่สุด!


ที่เกี่ยวข้อง: 1 , 2 , 3 , 4 , อาจจะมากกว่า
Peter Taylor

อาจจะคุ้มค่าที่จะมีกรณีทดสอบที่มีหน่วยเส้นขอบเดียวที่ตำแหน่งพิกัดเพื่อแสดงว่ามีเอาต์พุตที่ใช้ได้สองรายการ: กริดเต็มทั้งหมดหรือกริดไม่เปลี่ยนแปลง (ถ้าฉันเข้าใจบันทึกที่ 3 ของคุณถูกต้อง)
trichoplax

ดูตัวอย่าง 4) อัปเดต
shooqie

1
ฉันไม่เข้าใจว่าคุณได้รับตัวอย่างทางเลือกของคุณ 4 ที่ดูเหมือนว่าจะทำลายเซลล์เส้นขอบนอกเหนือจากตารางที่ระบุ
Joffan

คำตอบ:


4

MATLAB, 30 7 ไบต์

เนื่องจากเราสามารถใช้อินพุตแบบลอจิคัลแทนสตริงเราจึงสามารถใช้ฟังก์ชันเปล่าได้เนื่องจาก

@imfill

นี่คือฟังก์ชั่นที่ไม่ระบุชื่อ f=@imfillสำหรับการใช้งานที่เราต้องถือว่าชื่อเช่น จากนั้นเราก็สามารถประเมินเป็นf(input,point)ที่inputเป็นเมทริกซ์ตรรกะเช่น[0,0;0,1]และpointเป็น 2d เวกเตอร์ด้วยพิกัด 1-based [1,2]เช่น

เวอร์ชันเก่าทำงานกับสตริง:

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

ฟังก์ชันที่ไม่ระบุชื่อนี้ยอมรับอินพุตเช่นเดียวกับเวกเตอร์ที่มีพิกัด (ดัชนีแบบ 1 ฐาน) ฟังก์ชั่นimfillทำสิ่งที่เราต้องการอย่างแท้จริง แต่ทำงานเฉพาะในภาพไบนารี นั่นคือเหตุผลที่เราแปลงเมทริกซ์อินพุตเป็นโลจิคัลอาร์เรย์ (ซึ่ง#มีขอบเขตและ(ช่องว่าง) เป็นโมฆะ) ทำการเติมและเปลี่ยนกลับแล้ว ( #เติมเต็มแล้วพื้นที่ไม่เต็ม)

ขอบคุณ @LuisMendo สำหรับ - 1ไบต์


สำหรับเวอร์ชั่นสตริงคุณสามารถแทนที่~=32โดย>32
Luis Mendo

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ระหว่างแต่ละบรรทัดบรรทัดใหม่สุดท้ายเป็นตัวเลือก วิธีที่ง่ายที่สุดที่ฉันพบว่าเรียกใช้จาก shell:

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

เอาต์พุตไปยัง stdout โดยใช้!สำหรับอักขระการเติม หากตำแหน่งเริ่มต้นตรงกับ a #ทำให้ไม่มีการเปลี่ยนแปลง

ทำให้พังถล่ม:

                                    // 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;- เริ่มต้น gcc ให้intพิมพ์
Jacajack

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


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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.