50 lines
1.6 KiB
Nim
50 lines
1.6 KiB
Nim
import ./common, std/[strutils, sequtils, strformat, sugar, sets, math, algorithm]
|
|
|
|
proc toGrid(s: seq[string]): seq[seq[int]] =
|
|
for l in s: result.add(l.mapIt(int(it)-int('0')))
|
|
|
|
proc p1(c: seq[seq[int]]): int =
|
|
let h = c.len()
|
|
let w = c[0].len()
|
|
for y,l in c.pairs():
|
|
for x,n in l.pairs():
|
|
if x > 0 and c[y][x-1] <= n: continue
|
|
if y > 0 and c[y-1][x] <= n: continue
|
|
if x < w-1 and c[y][x+1] <= n: continue
|
|
if y < h-1 and c[y+1][x] <= n: continue
|
|
result += n + 1
|
|
|
|
proc p2(c: seq[seq[int]]): int =
|
|
let h = c.len()
|
|
let w = c[0].len()
|
|
var crawledPoints = toHashSet[(int, int)]([])
|
|
var basins: seq[int] = @[]
|
|
for y,l in c.pairs():
|
|
for x,n in l.pairs():
|
|
if crawledPoints.contains((x, y)): continue
|
|
crawledPoints.incl((x, y))
|
|
if n >= 9: continue
|
|
var eligiblePoints = toHashSet[(int, int)]([(x, y)])
|
|
var basin = 0
|
|
while eligiblePoints.len() > 0:
|
|
var newEligiblePoints = toHashSet[(int, int)]([])
|
|
for (cx,cy) in eligiblePoints:
|
|
inc basin
|
|
for (nx,ny) in [(cx-1,cy),(cx+1,cy),(cx,cy-1),(cx,cy+1)]:
|
|
if crawledPoints.contains((nx,ny)): continue
|
|
if nx >= 0 and nx < w and ny >= 0 and ny < h and c[ny][nx] < 9:
|
|
newEligiblePoints.incl((nx,ny))
|
|
crawledPoints.incl((nx,ny))
|
|
eligiblePoints = newEligiblePoints
|
|
basins.add(basin)
|
|
basins.sort(system.cmp[int], SortOrder.Descending)
|
|
basins[0] * basins[1] * basins[2]
|
|
|
|
doDay(9, (n) => n.loadInput().toGrid(),
|
|
p1,
|
|
p2,
|
|
"""2199943210
|
|
3987894921
|
|
9856789892
|
|
8767896789
|
|
9899965678""".split('\n').toGrid(), 15, 1134)
|