Riempi i laghi, 2D


22

La versione unidimensionale di questo problema era piuttosto semplice, quindi ecco una versione 2D più difficile.

Ti viene data una serie 2D di altezze di terra su input standard e devi capire dove si formeranno i laghi quando piove. La mappa di altezza è solo una matrice rettangolare dei numeri 0-9, inclusi.

8888888888
5664303498
6485322898
5675373666
7875555787

È necessario eseguire l'output dello stesso array, sostituendo tutte le posizioni che sarebbero sott'acqua *.

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

L'acqua può fuoriuscire in diagonale, quindi non ci sarebbe lago in questa configurazione:

888
838
388

vince il codice più breve. Il codice deve gestire dimensioni fino a 80 larghe e 24 alte.

Altri tre esempi:

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
Alcuni altri test sarebbero graditi, se possibile (soprattutto input, considereresti un caso limite).
Ventero,

È consentito lo spazio bianco finale nelle righe di output?
hallvabo

@hallvabo: no. Perché vorresti farlo?
Keith Randall,

Keith: avevo un'altra soluzione in cui ho riempito le linee di input a una larghezza fissa e salvato alcuni byte nell'algoritmo. Se devo rimuovere il padding per l'output, questo approccio richiede più byte rispetto alla mia soluzione attualmente migliore.
hallvabo,

Risposte:


7

Haskell, 258 personaggi

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

Esempio di esecuzione:

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

Supera tutti i test unitari. Nessun limite arbitrario per le dimensioni.


  • Modifica (281 → 258): non testare la stabilità, solo iterare al limite superiore; smettere di passare argomento costantem

5

Python, 483 491 caratteri

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

Sono abbastanza sicuro che ci sia un modo migliore (e più breve) per farlo


Per lo più funziona, ma ho dovuto sostituirlo input()con sys.stdin.read()e rimuovere il finale \ndalle mie ingressi campione.
Keith Randall,

@Keith Randall - sys.stdin.read()legge da un file giusto? Sono ancora piuttosto nuovo in Python.
Sistema inattivo

sys.stdin.read()legge STanDard INput fino a EOF. input()legge e valuta una riga di input standard.
Keith Randall,

4

Python, 478 471 caratteri

(Esclusi i commenti. 452 450 caratteri esclusi le importazioni.)

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

L'idea qui è che io costruisco un grafico diretto in cui ogni cella della griglia ha il suo vertice (più un vertice "drain" aggiuntivo). C'è un bordo nel grafico da ogni cella a valore più alto alle sue celle a valore inferiore vicine, inoltre c'è un bordo da tutte le celle esterne al vertice di "drenaggio". Quindi uso Floyd-Warshall per calcolare quali vertici sono collegati al vertice "drain"; tutti i vertici non collegati verranno allagati e disegnati con un asterisco.

Non ho molta esperienza con la condensazione del codice Python, quindi c'è probabilmente un modo più conciso che avrei potuto implementare questo metodo.


3

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

Non è stato fatto alcun tentativo di giocare a golf, ho appena trovato il problema interessante. L'input è l'array 2D della mappa. La soluzione controlla ogni quadrato per vedere se "drena" - un quadrato drena se si trova sul bordo esterno o se è adiacente a un quadrato di altezza uguale o inferiore che drena. Per evitare che si ripeta all'infinito, il codice mantiene una "mappa di drenaggio" (dm) in cui memorizza lo stato di drenaggio dei quadrati che sono già stati determinati.


La logica descritta non è del tutto corretta, in quanto non gestisce correttamente il caso con l'isola.
Keith Randall,

1

Python, 246 caratteri

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

La soluzione funziona eseguendo un DFS da ciascuna posizione per determinare se riempire o meno.

Se è consentito lo spazio bianco finale su ciascuna riga, è possibile accorciarlo utilizzando w = 80 e riempiendo le righe di input con spazio bianco a 80 caratteri.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.