เติมลงในทะเลสาบ 2D


22

รุ่นหนึ่งมิติของปัญหานี้ก็สวยง่ายดังนั้นนี่คือรุ่น 2D ยาก

คุณได้รับอาร์เรย์ความสูงของดิน 2 มิติจากอินพุตมาตรฐานและคุณต้องหาจุดที่ทะเลสาบจะก่อตัวเมื่อฝนตก แผนที่ความสูงเป็นเพียงรูปสี่เหลี่ยมผืนผ้าของตัวเลข 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

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

ผ่านการทดสอบหน่วยทั้งหมด ไม่มีการ จำกัด ขนาดโดยพลการ


  • แก้ไข (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()อ่านจากไฟล์ใช่มั้ย ฉันยังค่อนข้างใหม่ที่ Python
ระบบลดลง

sys.stdin.read()อ่าน STanDard INput จนกระทั่ง EOF input()อ่านและประเมินค่าหนึ่งบรรทัดของอินพุตมาตรฐาน
Keith Randall

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

ความคิดที่นี่คือฉันสร้างกราฟกำกับที่แต่ละเซลล์ตารางมีจุดสุดยอดของตัวเอง (บวกจุดยอด "ระบาย" เพิ่มเติมหนึ่ง) มีขอบในกราฟจากแต่ละเซลล์ที่มีมูลค่าสูงกว่าไปยังเซลล์ที่มีมูลค่าต่ำกว่าที่อยู่ใกล้เคียงรวมถึงมีขอบจากเซลล์ภายนอกทั้งหมดไปยังจุดยอด "ระบาย" จากนั้นฉันใช้Floyd-Warshallเพื่อคำนวณว่าจุดยอดไหนที่เชื่อมต่อกับจุดยอด "ท่อระบายน้ำ"; จุดยอดใด ๆ ที่ไม่ได้เชื่อมต่อจะถูกน้ำท่วมและวาดด้วยเครื่องหมายดอกจัน

ฉันไม่ได้มีประสบการณ์มากกับการย่อรหัส Python ดังนั้นอาจมีวิธีรวบรัดมากกว่าที่ฉันสามารถใช้วิธีนี้ได้


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

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.