호수를 채우고 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를 처리해야합니다.

세 가지 예 :

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
가능하다면 더 많은 테스트 케이스가 좋을 것입니다 (특히 입력은 에지 케이스를 고려할 것입니다).
Ventero

출력 라인에서 후행 공백이 허용됩니까?
hallvabo

@hallvabo : 아니요. 왜 하시겠습니까?
Keith Randall

Keith : 입력 줄을 고정 너비로 ​​채우고 알고리즘에 바이트를 저장하는 또 다른 솔루션이 있습니다. 출력 패딩을 제거 해야하는 경우이 방법은 현재 최상의 솔루션보다 더 많은 바이트를 사용합니다.
hallvabo

답변:


7

하스켈, 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

모든 단위 테스트를 통과합니다. 크기에 대한 제한은 없습니다.


  • 편집 (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

@ Keith Randall- sys.stdin.read()파일에서 바로 읽습니까? 나는 아직도 파이썬에서 새로운 사람입니다.
시스템 다운

sys.stdin.read()EOF까지 STanDard 입력을 읽습니다. input()한 줄의 표준 입력을 읽고 평가합니다.
Keith Randall

4

Python, 478471

(주석을 포함하지 않습니다. (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]))

여기서 아이디어는 각 그리드 셀에 고유 한 정점 (한 개의 추가 "드레인"정점)이있는 유향 그래프를 구성하는 것입니다. 더 높은 값의 각 셀에서 인접한 낮은 값의 셀까지 그래프의 가장자리가 있으며 모든 외부 셀에서 "드레인"정점까지의 가장자리가 있습니다. 그런 다음 Floyd-Warshall 을 사용 하여 "드레인"정점에 연결된 정점을 계산합니다. 연결 되지 않은 모든 정점은 침수되고 별표로 그려집니다.

파이썬 코드를 압축하는 데 많은 경험이 없으므로이 방법을 구현할 수있는 더 간결한 방법이있을 것입니다.


3

커먼 리스프, 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)을 유지합니다.


설명 된 논리는 섬의 경우를 올바르게 처리하지 못하기 때문에 옳지 않습니다.
Keith Randall

1

파이썬, 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.