Isi danau, 2D

22

Versi satu dimensi dari masalah ini cukup mudah, jadi inilah versi 2D yang lebih sulit.

Anda diberi array 2D ketinggian tanah pada input standar, dan Anda harus mencari tahu di mana danau akan terbentuk ketika hujan. Peta ketinggian hanyalah array persegi panjang dari angka 0-9, inklusif.

8888888888
5664303498
6485322898
5675373666
7875555787

Anda harus menampilkan larik yang sama, menggantikan semua lokasi yang akan menjadi air *.

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

Air dapat keluar secara diagonal, sehingga tidak ada danau dalam konfigurasi ini:

888
838
388

kode menang pendek. Kode Anda harus menangani ukuran hingga lebar 80 dan tinggi 24.

Tiga contoh lagi:

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
Keith Randall
sumber
4
Beberapa testcases lebih baik, jika mungkin (terutama input Anda akan mempertimbangkan kasus tepi).
Ventero
Apakah membuntuti spasi putih di jalur output diperbolehkan?
hallvabo
@hallvabo: tidak. Mengapa kamu mau?
Keith Randall
Keith: Saya punya solusi lain di mana saya mengisi jalur input dengan lebar tetap, dan menyimpan beberapa byte dalam algoritma. Jika saya harus menghapus padding untuk output, pendekatan ini membutuhkan lebih banyak byte daripada solusi terbaik saya saat ini.
hallvabo

Jawaban:

7

Haskell, 258 karakter

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

Contoh dijalankan:

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

Lulus semua tes unit. Tidak ada batasan ukuran ukuran.


  • Sunting (281 → 258): jangan menguji stabilitas, hanya beralih ke batas atas; berhenti lewat argumen konstanm
MtnViewMark
sumber
5

Python, 483 491 karakter

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

Saya cukup yakin ada cara yang lebih baik (dan lebih pendek) untuk melakukan ini

Sistem Down
sumber
Sebagian besar bekerja, tapi aku harus mengganti input()dengan sys.stdin.read()dan menghapus trailing \ndari input sampel saya.
Keith Randall
@Keith Randall - sys.stdin.read()membaca dari sebuah file bukan? Saya masih agak baru di Python.
Sistem Down
sys.stdin.read()membaca STanDard INput hingga EOF. input()membaca dan mengevaluasi satu baris input standar.
Keith Randall
4

Python, 478 471 karakter

(Tidak termasuk komentar. 452 450 karakter tidak termasuk impor.)

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

Idenya di sini adalah bahwa saya membangun grafik terarah di mana setiap sel jaringan memiliki simpul sendiri (ditambah satu simpul "tiriskan" tambahan). Ada tepi pada grafik dari masing-masing sel yang bernilai lebih tinggi ke sel-sel tetangganya yang bernilai lebih rendah di sebelahnya, ditambah ada tepi dari semua sel luar ke vertex "tiriskan". Saya kemudian menggunakan Floyd-Warshall untuk menghitung titik mana yang terhubung ke titik "tiriskan"; setiap simpul yang tidak terhubung akan dibanjiri dan digambar dengan tanda bintang.

Saya tidak punya banyak pengalaman dengan mengkondensasi kode Python, jadi mungkin ada cara yang lebih ringkas saya bisa menerapkan metode ini.

ESultanik
sumber
3

Common Lisp, 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 "~%")))))

Tidak ada upaya yang dilakukan untuk golf ini, saya baru saja menemukan masalah yang menarik. Input adalah array 2D dari peta. Solusinya memeriksa setiap kuadrat untuk melihat apakah "dikeringkan" - saluran kuadrat jika berada di tepi luar atau jika berdekatan dengan kuadrat tinggi yang sama atau lebih rendah yang mengalir. Agar tidak berulang tanpa henti, kode menyimpan "drain map" (dm) tempat ia menyimpan status drainase kotak yang telah ditentukan.

Dr. Pain
sumber
Logika yang Anda gambarkan kurang tepat, karena tidak menangani case dengan pulau dengan benar.
Keith Randall
1

Python, 246 karakter

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

Solusinya bekerja dengan melakukan DFS dari setiap posisi untuk menentukan apakah akan mengisi atau tidak.

Jika membuntuti spasi putih pada setiap baris diizinkan, itu dapat dipersingkat dengan menggunakan w = 80 dan mengisi garis input dengan spasi putih hingga 80 karakter.

hallvabo
sumber