Gölleri doldurun, 2D


22

Bu sorunun tek boyutlu versiyonu işte daha sert bir 2D versiyonu, oldukça kolaydı.

Standart girişte 2B'lik bir kara yüksekliği dizisi verilir ve yağmur yağdığında göllerin nerede oluşacağını bulmanız gerekir. Yükseklik haritası sadece 0-9 arasında sayılardan oluşan dikdörtgen bir dizidir.

8888888888
5664303498
6485322898
5675373666
7875555787

Su altında kalacak tüm yerleri değiştirerek aynı diziyi çıkarmalısınız *.

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

Su çapraz olarak kaçabilir, bu yüzden bu konfigürasyonda göl olmaz:

888
838
388

en kısa kod kazanır. Kodunuz 80 genişliğe ve 24 yüksekliğe kadar olan boyutları işlemelidir.

Üç örnek daha:

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ümkünse, bazı testisler daha iyi olurdu (özellikle girdi, bir uç vaka düşünün).
Hava

Çıktı satırlarındaki izlemenin boşluk bırakmasına izin var mı?
hallvabo

@hallvabo: hayır. Neden istiyorsun
Keith Randall

Keith: Giriş hatlarını sabit bir genişliğe sıkıştırdığım ve algoritmada bazı baytları sakladığım başka bir çözüm daha vardı. Çıktı için dolguyu kaldırmak zorunda kalırsam, bu yaklaşım şu anda en iyi çözümümden daha fazla bayt alır.
hallvabo

Yanıtlar:


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

Örnek çalışma:

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

Tüm birim testlerini geçer. Boyutta isteğe bağlı sınır yok.


  • Düzenleme (281 → 258): kararlılığı test etme, sadece üst sınıra gelme; sabit argüman geçmeyi bırakm

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

Bunu yapmanın daha iyi (ve daha kısa) bir yolu olduğundan eminim


Çoğunlukla işe yarıyor, ancak örnek girdilerimin sonundaki input()ile değiştirmek sys.stdin.read()ve kaldırmak zorunda \nkaldım.
Keith Randall

@Keith Randall - sys.stdin.read()bir dosyadan okuyor değil mi? Python'da hala yeniyim.
Sistem

sys.stdin.read()EOF'ye kadar STanDard Girişini okur. input()Standart girdilerin bir satırını okur ve değerlendirir.
Keith Randall

4

Python, 478 471 karakter

(Yorum içermez. 452 İthalatı içermeyen 450 karakter.)

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

Buradaki fikir, her ızgara hücresinin kendi tepe noktasına (artı bir ek "boşaltma" tepe noktasına) sahip olduğu yönlendirilmiş bir grafik oluşturmaktır. Grafikte her yüksek değerli hücreden komşu düşük değerli hücrelere kadar bir kenar vardır, ayrıca tüm dış hücrelerden "boşaltma" tepe noktasına bir kenar vardır. Daha sonra Floyd-Warshall'ı kullanarak hangi köşelerin “boşaltma” köşesine bağlı olduğunu hesaplamak için kullanıyorum ; Bağlı olmayan herhangi bir tepe noktası sular altında kalacak ve bir yıldız işaretiyle çizilecektir.

Python kodunu yoğunlaştırma konusunda fazla bir tecrübem yok, bu yüzden bu metodu uygulayabileceğim muhtemelen daha özlü bir yol var.


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

Bu golf için hiçbir girişimde bulunmadı, sadece sorunu ilginç buldum. Giriş, haritanın 2B dizisidir. Çözüm, her bir kareyi "boşalıp" olmadığını görmek için kontrol eder - bir kare boşalırsa, dış kenarda mı yoksa boşalmakta olan eşit yükseklikte bir kareye bitişik olup olmadığını. Sonsuza dek tekrar etmemek için, kod önceden belirlenmiş olan karelerin drenaj durumunu sakladığı bir "drenaj haritası" (dm) tutar.


Açıkladığınız mantık tam olarak doğru değil, çünkü adadaki durumu doğru ele almıyor.
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])

Çözüm, doldurup doldurmayacağınızı belirlemek için her konumdan bir DFS yaparak çalışır.

Her satırdaki izlemenin boşluk bırakılmasına izin verilirse, w = 80 kullanılarak ve giriş satırlarının boşlukla 80 karaktere getirilmesiyle kısaltılabilir.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.