Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- " Structure class for a Field of field of a plant: "
- Object subclass: Field [
- | plant plots neigh |
- Field class >> new: chr [^super new init: chr]
- init: chr [
- plant := chr.
- plots := Set new.
- neigh := Dictionary new.
- ^self
- ]
- addPlot: coord [^plots add: coord]
- addNeighbour: coord from: dir [
- ^(neigh at: coord ifAbsentPut: [Set new]) add: dir.
- ]
- " Perimeter is the number of ways into a neighbour: "
- perimeter [^neigh inject: 0 into: [:a :n | a + n size]]
- plant [^plant]
- plots [^plots]
- neighbours [^neigh]
- ]
- Object subclass: GardenGrid [
- | grid dirs dimX dimY |
- " Constructor: "
- GardenGrid class >> new: mapArray [^super new init: mapArray]
- init: mapArray [
- | sentinel |
- dimY := mapArray size + 2.
- dimX := mapArray first size + 2.
- dirs := {dimX. 1. -1 * dimX. -1}.
- " Add sentinels to all sides "
- sentinel := (1 to: dimX) inject: '' into: [:a :b | a, '.'].
- grid := sentinel, (mapArray collect: [:row | '.', row, '.']) join, sentinel.
- ^self
- ]
- " Returns direction left of dir: "
- widdershins: dir [
- ^dirs at: (dirs findFirst: [:el | el == dir]) \\ 4 + 1.
- ]
- " Find all Fields in grid and return a Set of them: "
- getFields [
- | fields field visited plant queue pos move |
- fields := Set new.
- visited := Set new.
- queue := OrderedCollection new.
- grid keysAndValuesDo: [:idx :plant |
- (plant == $.) | (visited includes: idx) ifFalse: [
- " Found a new Field, create it: "
- field := (Field new: plant) addPlot: idx; yourself.
- fields add: field.
- " BFS to find entire field and its neighbours: "
- queue add: idx.
- [queue notEmpty] whileTrue: [
- pos := queue removeFirst.
- (visited includes: pos) ifFalse: [
- dirs do: [:dir |
- move := pos + dir.
- ((grid at: move) == plant) ifTrue: [
- field addPlot: move.
- queue add: move.
- ] ifFalse: [
- field addNeighbour: move from: dir.
- ]
- ]
- ].
- visited add: pos.
- ]
- ]
- ].
- ^fields
- ]
- " Access: "
- at: idx [^grid at: idx]
- " Print grid on stream "
- printOn: aStream [
- (1 to: grid size) do: [:y |
- aStream nextPut: (grid at: y).
- (y \\ dimX = 0) ifTrue: [aStream nl].
- ]
- ]
- ]
- "
- | Mainline
- "
- grid := GardenGrid new: stdin lines contents.
- fields := grid getFields.
- part1 := fields inject: 0 into: [:a :f | a + (f plots size * f perimeter)].
- part2 := 0.
- fields do: [ :field |
- plant := field plant.
- corners := Set new.
- " Get corners of this field by going left around the perimeter: "
- field neighbours keysAndValuesDo: [:pos :dirs |
- dirs do: [:dir |
- left := grid widdershins: dir.
- corner := pos.
- [(field neighbours includesKey: corner) & ((grid at: corner - dir) == plant)] whileTrue: [
- corner := corner + left.
- ].
- " Plot found might have multiple corners, track directions we slide in: "
- corners add: (corner -> left).
- ]
- ].
- part2 := part2 + (field plots size * corners size).
- ].
- ('Part 1: %1' % {part1}) displayNl.
- ('Part 2: %1' % {part2}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement