Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- Collection extend [
- apply: method [ ^self collect: [:x | x perform: method] ]
- sum [ ^self inject: 0 into: [:a : b | a + b] ]
- product [ ^self inject: 1 into: [:a : b | a * b] ]
- ]
- "
- | Class to handle the 2D HeightMap, as well as tracking visited status for basin search
- "
- Object subclass: HeightMap [
- | grid xsize visit |
- dirs := { -1 @ 0. 0 @ -1. 1 @ 0. 0 @ 1 }.
- HeightMap class >> new: arrayStrings [
- ^(super new) init: arrayStrings.
- ]
- init: mapArray [
- xsize := (mapArray at: 1) size + 2.
- grid := Array new: mapArray size + 2.
- grid at: 1 put: (Array new: xsize withAll: 9).
- grid at: (grid size) put: (Array new: xsize withAll: 9).
- mapArray keysAndValuesDo: [ :i :line |
- | row |
- row := (OrderedCollection from: ((Array withAll: line) apply: #digitValue))
- addFirst: 9; addLast: 9; yourself.
- grid at: i+1 put: row asArray.
- ].
- visit := (1 to: grid size) collect: [:i | Array new: xsize withAll: false].
- ^self
- ]
- " Access to grid by Points "
- at: pt [
- ^(grid at: pt y) at: pt x
- ]
- " Get coordinates of neighbours "
- neighbours: pt [
- ^dirs collect: [ :d | pt + d ]
- ]
- " Execute a block on every Point of our input "
- pointDo: aBlock [
- (2 to: grid size - 1) do: [ :y |
- (2 to: xsize - 1) do: [ :x |
- aBlock value: (x@y).
- ]
- ]
- ]
- " Access to visit via Points "
- visit: pt [
- ^(visit at: pt y) at: pt x put: true.
- ]
- visited: pt [
- ^(visit at: pt y) at: pt x
- ]
- ]
- "
- | Mainline
- "
- map := HeightMap new: (stdin lines contents).
- "
- | Part 1
- "
- lows := OrderedCollection new.
- map pointDo: [ :pt |
- height := map at: pt.
- ((map neighbours: pt) conform: [:x | (map at: x) > height]) ifTrue: [
- lows add: pt.
- ]
- ].
- ('Part 1: %1' % {(lows collect: [:pt | (map at: pt) + 1]) sum}) displayNl.
- "
- | Part 2
- "
- basins := SortedCollection new.
- lows do: [ :low |
- (map visited: low) ifFalse: [
- size := 0.
- queue := OrderedCollection with: low.
- [queue notEmpty] whileTrue: [
- pos := queue removeFirst.
- ((map visited: pos) not and: [(map at: pos) < 9]) ifTrue: [
- map visit: pos.
- size := size + 1.
- queue addAllLast: (map neighbours: pos)
- ]
- ].
- basins add: size
- ]
- ].
- ('Part 2: %1' % {(basins reverse atAll: (1 to: 3)) product}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement