Điền vào hồ, 2D


22

Các phiên bản một chiều của vấn đề này là khá dễ dàng, vì vậy đây là một phiên bản khó khăn hơn 2D.

Bạn được cung cấp một mảng 2D độ cao đất trên đầu vào tiêu chuẩn và bạn phải tìm ra nơi các hồ sẽ hình thành khi trời mưa. Bản đồ chiều cao chỉ là một mảng hình chữ nhật của các số 0-9, đã bao gồm.

8888888888
5664303498
6485322898
5675373666
7875555787

Bạn phải xuất cùng một mảng, thay thế tất cả các vị trí sẽ ở dưới nước *.

8888888888
566*****98
6*85***898
5675*7*666
7875555787

Nước có thể thoát theo đường chéo, vì vậy sẽ không có hồ trong cấu hình này:

888
838
388

mã ngắn nhất thắng. Mã của bạn phải xử lý kích thước lên đến 80 rộng và 24 cao.

Ba ví dụ nữa:

77777    77777
75657    7*6*7
75757 => 7*7*7
77677    77677
77477    77477

599999    599999
933339    9****9
936639 => 9*66*9
935539    9*55*9
932109    9****9
999999    999999

88888888    88888888
84482288    8**8**88
84452233 => 8**5**33
84482288    8**8**88
88888888    88888888

4
Một số testcase sẽ tốt hơn, nếu có thể (đặc biệt là đầu vào bạn sẽ xem xét một trường hợp cạnh).
Ventero

Là khoảng trắng theo sau trong các dòng đầu ra được phép?
hallvabo

@hallvabo: không. Tại sao bạn sẽ muốn?
Keith Randall

Keith: Tôi đã có một giải pháp khác trong đó tôi đệm các dòng đầu vào theo chiều rộng cố định và lưu một số byte trong thuật toán. Nếu tôi phải loại bỏ phần đệm cho đầu ra, cách tiếp cận này cần nhiều byte hơn giải pháp tốt nhất hiện tại của tôi.
hallvabo

Câu trả lời:


7

Haskell, 258 ký tự

a§b|a<b='*'|1<3=a
z=[-1..1]
l m=zipWith(§)m$(iterate(b.q)$b(\_ _->'9'))!!(w*h)where
 w=length m`div`h
 h=length$lines m
 q d i=max$minimum[d!!(i+x+w*y)|x<-z,y<-z]
 b f=zipWith(\n->n`divMod`w¶f n)[0..]m
 (j,i)¶g|0<i&&i<w-2&&0<j&&j<h-1=g|1<3=id
main=interact l

Chạy ví dụ:

$> runhaskell 2638-Lakes2D.hs <<TEST
> 8888888888
> 5664303498
> 6485322898
> 5675373666
> 7875555787
> TEST
8888888888
566*****98
6*85***898
5675*7*666
7875555787

Vượt qua tất cả các bài kiểm tra đơn vị. Không có giới hạn tùy ý về kích thước.


  • Chỉnh sửa (281 → 258): không kiểm tra độ ổn định, chỉ lặp lại giới hạn trên; ngừng truyền đối số liên tụcm

5

Python, 483 491 ký tự

a=dict()
def s(n,x,y,R):
 R.add((x,y))
 r=range(-1,2)
 m=set([(x+i,y+j)for i in r for j in r if(i,j)!=(0,0)and(x+i,y+j)not in R])
 z=m-set(a.keys())
 if len(z)>0:return 1
 else:return sum(s(n,k[0],k[1],R)for k in[d for d in m-z if a[(d[0],d[1])]<=n])
i=[list(x)for x in input().strip().split('\n')]
h=len(i)
w=len(i[0])
e=range(0,w)
j=range(0,h)
for c in[(x,y)for x in e for y in j]:a[c]=int(i[c[1]][c[0]])
for y in j:print(''.join([('*',str(a[(x,y)]))[s(a[(x,y)],x,y,set())>0] for x in e]))

Tôi khá chắc chắn rằng có một cách tốt hơn (và ngắn hơn) để làm điều này


Chủ yếu là các công trình, nhưng tôi đã phải thay thế input()với sys.stdin.read()và loại bỏ các dấu \ntừ đầu vào mẫu của tôi.
Keith Randall

@Keith Randall - sys.stdin.read()đọc từ một tập tin phải không? Tôi vẫn còn khá mới với Python.
Hệ thống xuống

sys.stdin.read()đọc STanDard INput cho đến khi EOF. input()đọc và đánh giá một dòng đầu vào tiêu chuẩn.
Keith Randall

4

Con trăn, 478 471 ký tự

(Không bao gồm nhận xét. 452 450 ký tự không bao gồm nhập.)

import sys,itertools
i=[list(x)for x in sys.stdin.read().strip().split('\n')]
h=len(i)
w=len(i[0])
n=h*w
b=n+1
e=range(h)
d=range(w)
# j is, at first, the adjancency matrix of the graph.
# The last vertex in j is the "drain" vertex.
j=[[[b,1][(t-r)**2+(v-c)**2<=1 and i[r][c]>=i[t][v]] for t in e for v in d]+[[b,1][max([r==0,r>h-2,c==0,c>w-2])]]for r in e for c in d]+[[0]*b]
r=range(b)
for k,l,m in itertools.product(r,repeat=3):
    # This is the Floyd-Warshall algorithm
    if j[l][k]+j[k][m]<j[l][m]:
        j[l][m]=j[l][k]+j[k][m]
# j is now the distance matrix for the graph.
for k in r:
    if j[k][-1]>n:
        # This means that vertex k is not connected to the "drain" vertex, and is therefore flooded.
        i[k/w][k-w*(k/w)]='*'
for r in e:print(''.join(i[r]))

Ý tưởng ở đây là tôi xây dựng một biểu đồ có hướng trong đó mỗi ô lưới có đỉnh riêng (cộng với một đỉnh "thoát" bổ sung). Có một cạnh trong biểu đồ từ mỗi ô có giá trị cao hơn đến các ô có giá trị thấp hơn lân cận của nó, cộng với có một cạnh từ tất cả các ô bên ngoài đến đỉnh "thoát". Sau đó, tôi sử dụng Floyd-Warshall để tính toán các đỉnh được kết nối với đỉnh "cống"; bất kỳ đỉnh nào không được kết nối sẽ bị ngập và được vẽ bằng dấu hoa thị.

Tôi không có nhiều kinh nghiệm với việc cô đọng mã Python, vì vậy có lẽ có một cách ngắn gọn hơn mà tôi có thể thực hiện phương pháp này.


3

Lisp thường gặp, 833

(defun drains (terr dm a b)
  (cond
    ((= (aref dm a b) 1) t)
    ((= (aref dm a b) -1) nil)
    ((or (= a 0) (= b 0)
     (= a (1- (array-dimension terr 0)))
     (= b (1- (array-dimension terr 1)))) t)
    (t (loop for x from -1 to 1
       do (loop for y from 0 to 1
           do (if (and (or (> x 0) (> y 0))
                   (drains terr dm (+ a x) (+ b y))
                   (<= (aref terr (+ a x) (+ b y))
                   (aref terr a b)))
              (progn
                (setf (aref dm a b) 1)
                (return-from drains t)))))
    (setf (aref dm a b) -1)
    nil)))

(defun doit (terr)
  (let ((dm (make-array (array-dimensions terr))))
    (loop for x from 0 to (- (array-dimension terr 0) 1)
       do (loop for y from 0 to (- (array-dimension terr 1) 1)
         do (format t "~a"
            (if (drains terr dm x y)
                (aref terr x y)
                "*"))
         finally (format t "~%")))))

Không có nỗ lực đã được thực hiện để chơi golf này, tôi chỉ thấy vấn đề thú vị. Đầu vào là mảng 2D của bản đồ. Giải pháp kiểm tra từng ô vuông để xem nó "thoát" - một ô vuông thoát ra nếu nó nằm ở cạnh ngoài hoặc nếu nó nằm cạnh một hình vuông có chiều cao bằng hoặc thấp hơn thoát ra. Để tránh việc đệ quy không ngừng, mã giữ một "bản đồ thoát" (dm) nơi nó lưu trữ trạng thái thoát nước của các ô vuông đã được xác định.


Logic được mô tả của bạn không hoàn toàn đúng, vì nó không xử lý trường hợp chính xác với đảo.
Keith Randall

1

Python, ký tự 246

import os
a=list(os.read(0,2e3))
w=a.index('\n')+1
a+=' '*w
def f(p,t):
    if e<a[p]or p in t:return
    t[p]=1
    return'*'>a[p]or any(f(p+d,t)for d in(~w,-w,-w+1,-1,1,w-1,w,w+1))
z=0
for e in a:
    if(' '<e)*~-f(z,{}):a[z]='*'
    z+=1
print''.join(a[:~w])

Giải pháp hoạt động bằng cách thực hiện một DFS từ mỗi vị trí để xác định có nên điền hay không.

Nếu khoảng trắng theo dõi trên mỗi dòng được cho phép, nó có thể được rút ngắn bằng cách sử dụng w = 80 và đệm các dòng đầu vào có khoảng trắng đến 80 ký tự.

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.