湖を埋める、2D


22

この問題1次元バージョンは非常に簡単だったので、ここではより難しい2Dバージョンです。

標準入力で土地の高さの2D配列が与えられ、雨が降ると湖が形成される場所を把握する必要があります。高さマップは、0から9までの数字の単なる長方形の配列です。

8888888888
5664303498
6485322898
5675373666
7875555787

同じ配列を出力し、水中にあるすべての場所をに置き換える必要があります*

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

水は斜めに逃げることができるため、この構成では湖はありません。

888
838
388

最短のコードが勝ちます。コードは、最大幅80、高さ24までのサイズを処理する必要があります。

さらに3つの例:

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
可能であれば、さらにいくつかのテストケースがいいでしょう(特に入力はエッジケースと考えられます)。
ヴェンテロ

出力行の末尾の空白は許可されますか?
hallvabo

@hallvabo:いいえ。なぜしたいのですか?
キースランドール

キース:入力ラインを固定幅にパディングし、アルゴリズムにいくつかのバイトを保存する別のソリューションがありました。出力のパディングを削除する必要がある場合、このアプローチは現在の最良のソリューションよりも多くのバイトを必要とします。
hallvabo

回答:


7

Haskell、258文字

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

実行例:

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

すべての単体テストに合格します。サイズにarbitrary意的な制限はありません。


  • 編集(281→258):安定性をテストせず、上限まで繰り返します。定数引数を渡すのをやめるm

5

Python、483 491文字

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

私はこれを行うためのより良い(そしてより短い)方法があると確信しています


大部分は動作しますが、サンプル入力から末尾を置き換えinput()sys.stdin.read()削除する必要がありました\n
キースランドール

@Keith Randall- sys.stdin.read()ファイルから読み取りますか?私はまだPythonの初心者です。
システムダウン

sys.stdin.read()EOFまでSTanDard INputを読み取ります。 input()標準入力の1行を読み取り、評価します。
キースランドール

4

Python、478 471文字

(コメントは含まれません。 インポートを含まない452 450文字。)

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

ここでのアイデアは、各グリッドセルが独自の頂点(および「ドレイン」頂点を1つ追加)を持つ有向グラフを構築することです。グラフには、高値の各セルから隣接する低値のセルへのエッジがあり、さらにすべての外部セルから「ドレイン」頂点へのエッジがあります。次に、Floyd-Warshallを使用して、どの頂点が「ドレイン」頂点に接続されているかを計算します。接続されていない頂点は塗りつぶされ、アスタリスクで描画されます。

Pythonコードを凝縮した経験はあまりないので、おそらくこのメソッドを実装できるもっと簡潔な方法があるでしょう。


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

これをゴルフしようとする試みは行われていません、私はちょうど問題が面白いとわかりました。入力は、マップの2D配列です。ソリューションは、各正方形をチェックして、それが「排水」するかどうかを確認します。正方形が外縁にある場合、または排水する同等または低い高さの正方形に隣接している場合、正方形は排水します。無限に再帰しないように、コードは「ドレインマップ」(dm)を保持します。このマップには、すでに決定されている正方形の排水状態が格納されます。


説明したロジックは、アイランドのケースを正しく処理しないため、完全に正しくありません。
キースランドール

1

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

ソリューションは、各位置からDFSを実行して、満たすかどうかを決定します。

各行の末尾の空白が許可されている場合、w = 80を使用し、入力行に空白を80文字まで埋め込むことで短縮できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.