63 lines
2 KiB
Smalltalk
63 lines
2 KiB
Smalltalk
Grid subclass: HeightMap [
|
|
| invHeights |
|
|
rows: r [super rows: r. self initInvHeights]
|
|
|
|
initInvHeights
|
|
[invHeights := (0 to: 9) collect: [:h | (super allPosnsOf: h) asArray]]
|
|
|
|
allPosnsOf: h [^invHeights at: h + 1]
|
|
]
|
|
|
|
Object subclass: TrailMap [
|
|
| heightMap scores allDirs heightsRev |
|
|
scores [^scores]
|
|
|
|
initFor: pos [ ^Set new add: pos; yourself ]
|
|
initScore [ ^Set new ]
|
|
combineScore: score with: other [ score addAll: other. ^score ]
|
|
numberFromScore: score [ ^score size ]
|
|
|
|
initialize [ allDirs := {Posn up. Posn down. Posn left. Posn right}. ]
|
|
heights: hm [ heightMap := hm. self initScores. ]
|
|
initScores
|
|
[ scores :=
|
|
Grid width: heightMap width height: heightMap height
|
|
initWith: [
|
|
:pos | ((heightMap at: pos) = 9)
|
|
ifTrue: [self initFor: pos]
|
|
ifFalse: [nil]] ]
|
|
|
|
computeScores
|
|
[ (8 to: 0 by: -1) do: [:i | self computeScoresForHeight: i]. ]
|
|
|
|
computeScoresForHeight: h
|
|
[ | h1 | h1 := h + 1.
|
|
(heightMap allPosnsOf: h) do: [
|
|
:pos | | res | res := self initScore.
|
|
allDirs collect: [
|
|
:off | | offp | offp := pos + off.
|
|
((heightMap at: offp) = h1) ifTrue: [
|
|
res := self combineScore: res with: (scores at: offp) ]].
|
|
scores at: pos put: res ]]
|
|
|
|
trailheadScores
|
|
[ ^(heightMap allPosnsOf: 0) collect: [
|
|
:p | self numberFromScore: (scores at: p)] ]
|
|
]
|
|
|
|
TrailMap subclass: TrailMapP2 [
|
|
initFor: pos [^1]
|
|
initScore [^0]
|
|
combineScore: score with: other [^score + other]
|
|
numberFromScore: score [^score]
|
|
]
|
|
|
|
AOC input: [ | rows |
|
|
rows := stdin toLines asArray collect: [
|
|
:line | line asArray collect: [:it | it digitValue]].
|
|
HeightMap new rows: rows ];
|
|
part1: TrailMap; part2: TrailMapP2;
|
|
result: [ :heights :Class | | map |
|
|
map := Class new heights: heights.
|
|
map computeScores trailheadScores sum ];
|
|
finish.
|