Bản đồ quần đảo (và một dòng sông)


20

Giới thiệu

Trong nhiều thế kỷ, đã có một con sông nhất định chưa bao giờ được lập bản đồ. Hội những người vẽ bản đồ muốn tạo ra một bản đồ của dòng sông, tuy nhiên, họ chưa bao giờ thành công - vì một lý do nào đó, tất cả những người vẽ bản đồ mà họ đã gửi để lập bản đồ dòng sông đã bị thú hoang ăn trong khu vực. Một cách tiếp cận khác nhau là cần thiết.

Mô tả đầu vào

Khu vực này là một lưới hình chữ nhật gồm các ô có chiều dài mvà chiều rộng n. Ô ở phía dưới bên trái sẽ là 0,0và ô ở phía trên bên phải sẽ là m-1,n-1. mnđược cung cấp trong đầu vào dưới dạng một tuple m,n.

Bằng cách sử dụng các kỹ thuật âm thanh địa lý đường dài, vị trí của các đảo xung quanh sông đã được xác định. Kích thước của các hòn đảo (tức là có bao nhiêu tế bào mà hòn đảo chiếm giữ) cũng đã được xác định nhưng hình dạng thì không. Chúng tôi cung cấp thông tin này trong một tuple s,x,yskích thước của hòn đảo xylà vị trí x và y của một ô cụ thể của đảo đó. Mỗi bộ dữ liệu trong đầu vào được phân tách không gian, vì vậy đây là một ví dụ đầu vào:

7,7 2,0,0 2,3,1 2,6,1 2,4,3 2,2,4 8,0,6 1,2,6 3,4,6

Để minh họa rõ hơn, đây là đầu vào trên biểu đồ:

 y 6|8 1 3
   5|
   4|  2
   3|    2
   2|
   1|   2  2
   0|2  
     =======
     0123456
     x

Mô tả đầu ra

Xuất bản đồ bằng các ký tự ASCII để thể hiện các phần của khu vực. Mỗi ô sẽ là #(đất) hoặc .(nước). Bản đồ phải tuân theo các quy tắc sau:

  1. Định nghĩa. Một hòn đảo là một nhóm các tế bào đất liền kề trực giao được giới hạn hoàn toàn bởi các tế bào sông và / hoặc biên giới của khu vực.
  2. Định nghĩa. Sông là một nhóm các tế bào nước tiếp giáp trực giao, được giới hạn hoàn toàn bởi các tế bào đất và / hoặc biên giới của khu vực, không chứa "hồ" (2x2 khu vực của các tế bào nước).
  3. Quy tắc . Bản đồ sẽ chứa chính xác một con sông.
  4. Quy tắc . Mỗi ô được đánh số trong đầu vào phải là một phần của đảo chứa chính xác scác ô.
  5. Quy tắc . Mỗi đảo trong bản đồ phải chứa chính xác một trong các ô được đánh số trong đầu vào.
  6. Quy tắc . Có tồn tại một bản đồ duy nhất cho mỗi đầu vào.

Đây là đầu ra của ví dụ đầu vào:

#.#.##.
#....#.
#.##...
##..##.
###....
...##.#
##....#

Đây là một đầu vào và đầu ra.

Đầu vào:

5,5 3,0,1 1,4,1 2,0,4 2,2,4 2,4,4

Đầu ra:

#.#.#
#.#.#
.....
###.#
.....

3
Lưu ý: đây là câu hỏi tương tự như người giải Nurikabe .
absinthe

1
Chúng ta có thể lấy đầu vào ở bất kỳ định dạng thuận tiện nào không, hay chúng ta nên bám vào câu hỏi trong câu hỏi?
Erik the Outgolfer

1
đây cũng là vấn đề 4 từ cuộc thi Dyalog 2012
ngn

@ngn Từ khi nào "đăng băm mật mã" ... thông thường? (nhưng tôi cho rằng nó được cho phép khi một thách thức cho phép rõ ràng)
user202729

1
đây là một bookmarklet cho puzzle-nurikabe.com - nó chuyển đổi câu đố hiện tại thành một đầu vào hợp lệ cho thử thách này và hiển thị nó màu đỏ ngay dưới bảng:javascript:(_=>{var t=Game.nurikabe().task,m=t.length,n=t[0].length,s=[m,n];for(var i=0;i<m;i++)for(var j=0;j<n;j++)if(t[i][j]>=0)s+=' '+[t[i][j],i,j];puzzleContainerDiv.insertAdjacentHTML('beforeend','<hr><tt style=color:red>'+s+'</tt><hr>')})();void(0)
ngn

Câu trả lời:


10

C + PicoSAT , 2345 995 952 byte

#include<picosat.h>
#define f(i,a)for(i=a;i;i--)
#define g(a)picosat_add(E,a)
#define b calloc(z+1,sizeof z)
#define e(a,q)if(a)A[q]^A[p]?l[q]++||(j[++k]=q):s[q]||(i[q]=p,u(q));
z,F,v,k,n,h,p,q,r,C,*x,*A,*i,*l,*s,*j,*m;u(p){s[m[++n]=p]=1;e(p%F-1,p-1)e(p%F,p+1)e(p>F,p-F)e(p<=F*v-F,p+F)}t(){f(q,k)l[j[q]]=0;f(q,n)s[m[q]]=0;k=n=0;i[p]=-1;u(p);}main(){void*E=picosat_init();if(scanf("%d,%d",&F,&v)-2)abort();z=F*v;for(x=b;scanf("%d,%d,%d",&r,&p,&q)==3;g(p),g(0))x[p=F-p+q*F]=r;f(p,F*v-F)if(p%F)g(p),g(p+1),g(p+F),g(p+F+1),g(0);for(A=b,i=b,l=b,s=b,j=b,m=b;!C;){picosat_sat(E,C=h=-1);f(p,F*v)A[p]=picosat_deref(E,p)>0,i[p]=0;f(p,F*v)if(x[p])if(i[q=p]){for(g(-q);i[q]+1;)q=i[q],g(-q);g(C=0);}else if(t(),r=n-x[p]){f(q,r<0?k:n)g(r<0?j[q]:-m[q]);g(C=0);}f(p,F*v)if(!i[p])if(t(),A[p]){g(-++z);f(q,k)g(j[q]);g(C=0);f(q,n)g(-m[q]),g(z),g(0);}else{C&=h++;f(q,k)g(-j[q]);g(++z);g(++z);g(0);f(q,F*v)g(s[q]-z),g(q),g(0);}}f(p,F*v)putchar(A[p]?35:46),p%F-1||puts("");}

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

(Cảnh báo: liên kết TIO này là URL 30 kilobyte có chứa bản sao được rút gọn của PicoSAT 965, do đó bạn có thể không tải được nó trong một số trình duyệt, nhưng nó tải ít nhất Firefox và Chrome.)

Làm thế nào nó hoạt động

Chúng tôi khởi tạo bộ giải SAT với một biến cho mỗi ô (đất hoặc nước) và chỉ các ràng buộc sau:

  1. Mỗi ô được đánh số là đất.
  2. Mỗi hình chữ nhật 2 × 2 có ít nhất một vùng đất.

Phần còn lại của các ràng buộc khó mã hóa trực tiếp vào SAT, vì vậy thay vào đó chúng tôi chạy bộ giải để lấy mô hình, chạy một chuỗi các tìm kiếm theo chiều sâu để tìm các vùng được kết nối của mô hình này và thêm các ràng buộc bổ sung như sau:

  1. Đối với mỗi ô được đánh số trong một vùng đất quá lớn, hãy thêm một ràng buộc rằng phải có ít nhất một ô nước trong số các ô đất hiện tại trong vùng đó.
  2. Đối với mỗi ô được đánh số trong một vùng đất quá nhỏ, hãy thêm một ràng buộc rằng phải có ít nhất một ô đất trong số các ô nước hiện tại giáp với vùng đó.
  3. Đối với mỗi ô được đánh số trong cùng một vùng đất với một ô được đánh số khác, hãy thêm một ràng buộc rằng phải có ít nhất một ô nước dọc theo đường đi của các ô đất hiện tại giữa chúng (được tìm thấy bằng cách đi bộ con trỏ cha mẹ còn sót lại từ tìm kiếm đầu tiên ).
  4. Đối với mọi vùng đất bao gồm không có ô được đánh số, hãy thêm các ràng buộc
    • Tất cả các tế bào đất hiện tại phải là nước, hoặc
    • ít nhất một trong những tế bào nước hiện tại giáp với khu vực đó phải là đất liền.
  5. Đối với mọi vùng nước, hãy thêm các ràng buộc
    • tất cả các tế bào nước hiện tại phải là đất, hoặc
    • mọi tế bào không phải là những tế bào nước hiện tại phải là đất, hoặc
    • ít nhất một trong những tế bào đất hiện tại giáp với khu vực đó phải là nước.

Tận dụng giao diện gia tăng cho thư viện PicoSAT, chúng ta có thể ngay lập tức chạy lại bộ giải bao gồm các ràng buộc được thêm vào, bảo toàn tất cả các suy luận trước đó của bộ giải. PicoSAT cung cấp cho chúng tôi một mô hình mới và chúng tôi tiếp tục lặp lại các bước trên cho đến khi giải pháp hợp lệ.

Điều này là hiệu quả rõ rệt; nó giải quyết các trường hợp 15 × 15 và 20 × 20 trong một phần rất nhỏ của một giây.

(Cảm ơn Lopsy đã gợi ý ý tưởng này về việc hạn chế tương tác các vùng được kết nối trong một bộ giải SAT gia tăng, một thời gian trước.)

Một số trường hợp thử nghiệm lớn hơn từ puzzle-nurikabe.com

Một trang ngẫu nhiên gồm các câu đố khó 15 × 15 ( 5057541 , 5122197 , 5383030 , 6275294 , 6646970 , 6944232 ):

15,15 1,5,1 3,9,1 5,4,2 1,6,2 2,11,2 2,2,3 3,9,3 2,4,4 1,10,4 5,12,4 3,1,5 1,3,5 3,8,5 1,13,5 5,5,6 1,12,6 1,2,8 2,9,8 1,1,9 2,6,9 6,11,9 3,13,9 5,2,10 2,4,10 4,10,10 1,5,11 2,12,11 2,3,12 2,8,12 5,10,12 1,5,13 1,9,13 1,6,14 1,8,14
15,15 4,2,0 2,5,0 1,3,1 2,14,2 1,3,3 2,11,3 1,13,3 1,5,4 11,7,4 1,9,4 1,4,5 1,8,5 2,10,5 12,14,5 3,5,6 1,4,7 2,10,7 3,9,8 4,0,9 1,4,9 1,6,9 3,10,9 1,5,10 1,7,10 8,9,10 1,1,11 10,3,11 2,11,11 6,0,12 1,11,13 2,9,14 1,12,14
15,15 2,2,0 8,10,0 2,3,1 2,14,2 2,3,3 3,5,3 3,9,3 2,11,3 5,13,3 6,0,4 3,7,4 3,3,5 2,11,5 2,6,6 1,8,6 1,4,7 2,10,7 1,6,8 2,8,8 5,3,9 2,11,9 2,7,10 7,14,10 2,1,11 4,3,11 2,5,11 1,9,11 2,11,11 2,0,12 4,6,13 1,11,13 3,4,14 1,12,14
15,15 2,0,0 2,4,0 3,6,1 2,10,1 1,13,1 2,5,2 2,12,2 3,0,3 2,2,3 4,7,3 2,9,3 1,14,3 1,4,4 1,8,4 2,12,5 4,2,6 3,4,6 1,14,6 7,7,7 1,10,8 2,12,8 3,2,9 2,14,9 2,0,10 2,6,10 1,10,10 2,5,11 4,7,11 2,12,11 1,14,11 3,2,12 3,9,12 1,1,13 2,4,13 3,8,13 2,10,14 5,14,14
15,15 1,3,0 1,14,0 3,7,1 3,10,1 2,13,1 3,1,2 4,5,2 2,12,3 3,3,4 1,8,4 1,1,5 3,5,5 1,9,5 5,13,5 3,3,6 1,8,6 2,2,7 2,12,7 1,6,8 1,8,8 2,11,8 2,1,9 4,5,9 2,9,9 2,13,9 2,6,10 4,11,10 1,2,11 3,9,12 2,13,12 3,1,13 2,4,13 3,7,13 1,0,14
15,15 2,8,0 2,4,1 2,7,1 1,10,1 6,4,3 1,1,4 12,5,4 3,11,4 5,13,4 3,10,5 3,0,6 1,6,6 2,8,6 4,13,7 2,3,8 1,6,8 3,8,8 2,14,8 2,4,9 5,1,10 4,3,10 1,9,10 6,13,10 3,8,11 1,10,11 3,4,13 2,7,13 3,10,13 1,6,14 1,14,14

Một trang ngẫu nhiên gồm 20 × 20 câu đố thông thường ( 536628 , 3757659 ):

20,20 1,0,0 3,2,0 2,6,0 1,13,0 3,9,1 3,15,1 2,7,2 3,13,2 3,0,3 2,3,3 3,18,3 3,5,4 2,9,4 2,11,4 2,16,4 1,0,5 2,7,5 1,10,5 1,19,5 3,2,6 1,11,6 2,17,6 2,0,7 3,4,7 5,6,7 2,9,7 4,13,7 3,15,7 1,3,8 1,10,8 1,14,9 2,18,9 3,1,10 2,4,10 1,8,10 1,10,10 3,12,10 3,16,10 1,9,11 1,17,11 2,19,11 2,0,12 2,2,12 1,4,12 4,6,12 2,13,12 2,15,12 1,14,13 2,17,13 1,3,14 2,5,14 4,7,14 2,15,14 3,0,15 1,2,15 2,13,15 3,18,15 3,7,16 7,10,16 1,17,16 2,0,17 2,3,17 2,5,17 3,11,17 3,15,17 1,0,19 1,2,19 1,4,19 2,6,19 5,8,19 1,11,19 1,13,19 3,15,19 2,18,19
20,20 1,0,0 1,4,0 5,8,0 1,17,0 1,19,0 2,17,2 3,6,3 2,10,3 2,12,3 4,14,3 6,0,4 3,4,4 4,7,4 1,11,4 1,18,4 1,6,5 3,12,5 4,15,5 4,4,6 2,16,6 2,19,6 6,0,7 3,10,7 2,12,8 2,17,8 3,3,9 2,5,9 4,8,9 2,10,9 3,0,10 1,2,10 5,14,10 2,16,10 2,19,10 7,7,11 3,12,12 2,17,12 2,2,13 4,4,13 3,6,13 4,14,13 3,0,14 1,3,14 1,5,14 3,16,14 1,2,15 1,9,15 2,11,15 5,13,15 3,19,15 1,4,16 3,6,16 1,3,17 1,12,17 1,14,17 1,16,17 6,0,19 2,2,19 3,5,19 2,7,19 5,9,19 1,11,19 2,13,19 1,15,19 4,17,19

3

GLPK , (không cạnh tranh) 2197 byte

Đây là một mục không cạnh tranh, như

  • Tôi không tuân theo định dạng dữ liệu đầu vào (vì GLPK chỉ có thể đọc dữ liệu đầu vào từ các tệp) và
  • GLPK dường như không có sẵn trên RIO.

Tôi sẽ lưu một phiên bản vẫn chưa được chỉnh sửa nhưng vẫn hoạt động ở đây. Tùy thuộc vào phản hồi, tôi có thể cố gắng rút ngắn nó + thêm một lời giải thích nếu có sự quan tâm. Cho đến nay, các tên ràng buộc phục vụ như các tài liệu tại chỗ.

Ý tưởng chính là mã hóa ràng buộc "các đảo liền kề" bằng cách đưa ra một biến dòng được bảo toàn có nguồn được chỉ định trước tại vị trí gợi ý. Biến quyết định is_islandsau đó đóng vai trò của các bồn rửa có thể gắn được. Bằng cách giảm thiểu tổng số dòng chảy này, các đảo buộc phải duy trì kết nối ở mức tối ưu. Các ràng buộc khác thay vì trực tiếp thực hiện các quy tắc khác nhau. Điều gì làm tôi bối rối mà dường như tôi vẫn cầnisland_fields_have_at_least_one_neighbor .

Hiệu suất của công thức này là không tuyệt vời, mặc dù. Bằng cách ăn trực tiếp tất cả sự phức tạp với một lượng lớn các ràng buộc, bộ giải mất gần 15 giây cho ví dụ 15 x 15.

Mã (vẫn chưa được xử lý)

# SETS
param M > 0, integer; # length
param N > 0, integer; # width
param P > 0, integer; # no. of islands

set X := 0..N-1;  # set of x coords
set Y := 0..M-1;  # set of y coords
set Z := 0..P-1;  # set of islands

set V := X cross Y;
set E within V cross V := setof{
  (sx, sy) in V, (tx, ty) in V :

  ((abs(sx - tx) = 1) and (sy = ty)) or 
  ((sx = tx) and (abs(sy - ty) = 1))
} 
  (sx, sy, tx, ty);


# PARAMETERS
param islands{x in X, y in Y, z in Z}, integer, default 0;
param island_area{z in Z} := sum{x in X, y in Y} islands[x, y, z];

# VARIABLES
var is_river{x in X, y in Y}, binary;
var is_island{x in X, y in Y, z in Z}, binary;
var flow{(sx, sy, tx, ty) in E, z in Z} >= 0;

# OBJECTIVE
minimize obj: sum{(sx, sy, tx, ty) in E, z in Z} flow[sx, sy, tx, ty, z];

# CONSTRAINTS
s.t. islands_are_connected{(x, y) in V, z in Z}:

    islands[x, y, z] 
  - is_island[x, y, z]
  + sum{(sx, sy, tx, ty) in E: x = tx and y = ty} flow[sx, sy, x, y, z]
  - sum{(sx, sy, tx, ty) in E: x = sx and y = sy} flow[x, y, tx, ty, z]
  = 0;


s.t. island_contains_hint_location{(x, y) in V, z in Z}:

    is_island[x, y, z] >= if islands[x, y, z] > 0 then 1 else 0;


s.t. each_square_is_river_or_island{(x, y) in V}:

    is_river[x, y] + sum{z in Z} is_island[x, y, z] = 1;


s.t. islands_match_hint_area{z in Z}:

    sum{(x, y) in V} is_island[x, y, z] = island_area[z];


s.t. river_has_no_lakes{(x,y) in V: x > 0 and y > 0}:

  3 >= is_river[x, y] + is_river[x - 1, y - 1]
     + is_river[x - 1, y] + is_river[x, y - 1];


s.t. river_squares_have_at_least_one_neighbor{(x, y) in V}:

    sum{(sx, sy, tx, ty) in E: x = tx and y = ty} is_river[sx, sy] 
 >= is_river[x, y];


s.t. island_fields_have_at_least_one_neighbor{(x, y) in V, z in Z: island_area[z] > 1}:

    sum{(sx, sy, tx, ty) in E: x = tx and y = ty} is_island[sx, sy, z]
 >= is_island[x, y, z];


s.t. islands_are_separated_by_water{(x, y) in V, z in Z}:

    sum{(sx, sy, tx, ty) in E, oz in Z: x = sx and y = sy and z != oz} is_island[tx, ty, oz]
 <= 4 * P * (1 - is_island[x, y, z]);

solve;

for{y in M-1..0 by -1}
{
    for {x in X} 
    {
        printf "%s", if is_river[x, y] = 1 then "." else "#";
    }
    printf "\n";
}

Dữ liệu vấn đề

5 x 5

data;
param M := 5;
param N := 5;
param P := 5;
param islands :=
# x,y,z,area
  0,1,0,3
  4,1,1,1
  0,4,2,2
  2,4,3,2
  4,4,4,2;
end;

7 x 7

data;
param M := 7;
param N := 7;
param P := 8;
param islands :=
# x,y,z,area
  0,0,0,2 
  3,1,1,2 
  6,1,2,2 
  4,3,3,2 
  2,4,4,2 
  0,6,5,8 
  2,6,6,1 
  4,6,7,3;
end;

15 x 15

data;
param M := 15;
param N := 15;
param P := 34;
param islands :=
# x,y,   z,area
5,  1,   0, 1
9,  1,   1, 3
4,  2,   2, 5
6,  2,   3, 1
11, 2,   4, 2
2,  3,   5, 2
9,  3,   6, 3
4,  4,   7, 2
10, 4,   8, 1
12, 4,   9, 5
1,  5,  10, 3
3,  5,  11, 1
8,  5,  12, 3
13, 5,  13, 1
5,  6,  14, 5
12, 6,  15, 1
2,  8,  16, 1
9,  8,  17, 2
1,  9,  18, 1
6,  9,  19, 2
11, 9,  20, 6
13, 9,  21, 3
2,  10, 22, 5
4,  10, 23, 2
10, 10, 24, 4
5,  11, 25, 1
12, 11, 26, 2
3,  12, 27, 2
8,  12, 28, 2
10, 12, 29, 5
5,  13, 30, 1
9,  13, 31, 1
6,  14, 32, 1
8,  14  33, 1;
end;

Sử dụng

Đã glpsolcài đặt, mô hình hóa dưới dạng một tệp (ví dụ river.mod), dữ liệu đầu vào trong (các) tệp riêng biệt (ví dụ 7x7.mod). Sau đó:

glpsol -m river.mod -d 7x7.mod

Điều này cộng với một số kiên nhẫn sẽ in giải pháp ở định dạng đầu ra được chỉ định (cùng với đầu ra chẩn đoán "một số").


2
Tôi nghĩ rằng câu trả lời này nên được coi là cạnh tranh vì người khác có thể xác minh rằng nó hoạt động. Sự khác biệt trong định dạng IO phải được bao hàm bởi giả định rằng mọi định dạng IO hợp lý đều phải được chấp nhận.
fnɛtɪk

2
@ fəˈnɛtɪk Đồng ý. Nó không đủ điều kiện cho tiền thưởng của ngn vừa kết thúc, trong đó đặc biệt yêu cầu một câu trả lời có thể chạy được trên TIO, nhưng đó không phải là một yêu cầu của chính câu hỏi.
Anders Kaseorg

Cho rằng tôi chưa bắt đầu chơi golf, tôi sẽ không xem nó thi đấu (chưa). Khi tôi chắc chắn rằng mình đã loại bỏ tất cả các ràng buộc dư thừa, tôi sẽ thực hiện một lần tất cả các khai báo.
ojdo

3

Python 3 , 1295 byte

Đây là một giải pháp chỉ trăn. Nó không sử dụng thư viện và tải bảng thông qua đầu vào tiêu chuẩn. Giải thích thêm để đến. Đây là nỗ lực đầu tiên của tôi tại một sân golf lớn như vậy. Có một liên kết đến mã nhận xét và không có golf ở phía dưới.

L,S,O,R,F=len,set,None,range,frozenset
U,N,J,D,I=S.update,F.union,F.isdisjoint,F.difference,F.intersection
def r(n,a,c):
 U(c,P)
 if L(I(N(Q[n],C[n]),a))<2:return 1
 w=D(P,N(a,[n]));e=S();u=S([next(iter(w))])
 while u:n=I(Q[u.pop()],w);U(u,D(n,e));U(e,n)
 return L(e)==L(w)
def T(a,o,i,c,k):
 s,p,m=a
 for _ in o:
  t=s,p,N(m,[_]);e=D(o,[_])
  if t[2] in c:o=e;continue
  c.add(t[2]);n=D(Q[_],m);U(k,n)
  if not J(i,n)or not r(_,N(m,i),k):o=e
  elif s==L(t[2]):yield t
  else:yield from T(t,N(e,n),i,c,k)
s,*p=input().split()
X,Y=eval(s)
A=[]
l=1,-1,0,0
P=F((x,y)for y in R(Y)for x in R(X))
exec("Q%sl,l[::-1]%s;C%s(1,1,-1,-1),l[:2]*2%s"%(('={(x,y):F((x+i,y+j)for i,j in zip(',')if X>x+i>-1<y+j<Y)for x,y in P}')*2))
for a in p:a,x,y=eval(a);k=x,y;A+=[(a,k,F([k]))]
A.sort(reverse=1)
k=F(a[1]for a in A)
p=[O]*L([a for a in A if a[0]!=1])
g,h=p[:],p[:]
i=0
while 1:
 if g[i]is O:h[i]=S();f=O;g[i]=T(A[i],Q[A[i][1]],D(N(k,*p[:i]),[A[i][1]]),S(),h[i])
 try:p[i]=g[i].send(f)[2]
 except:
  f=I(N(k,*p[:i]),h[i]);g[i]=p[i]=O;i-=1
  while J(p[i],f):g[i]=p[i]=O;i-=1
 else:
  i+=1
  if i==L(p):
   z=N(k,*p)
   if not any(J(z,F(zip([x,x+1]*2,[y,y,y+1,y+1])))for x in R(X-1)for y in R(Y-1)):break
   for c in h:U(c,z)
b=[X*['.']for i in R(Y)]
for x,y in z:b[y][x]='#'
for l in b[::-1]:print(''.join(l))

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

Nhìn vào mã không chơi gôn .

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.