Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- " Uses a flat array (String) for the grid, with sentinel #s inserted "
- Object subclass: TreeGrid [
- | grid dims dirs |
- TreeGrid class >> new: textArray [
- ^super new init: textArray
- ]
- init: textArray [
- | sent |
- dims := (textArray at: 1) size @ textArray size.
- " Flatten and add sentinel rows to top. bottom, and between rows "
- sent := (1 to: dims x + 1) inject: '' into: [:a :b | a, '#'].
- grid := sent, (textArray collect: [:x | x, '#']) join, sent.
- dirs := Dictionary from: {
- #right -> 1.
- #left -> -1.
- #down -> (dims x + 1).
- #up -> (dims x + 1) negated.
- }.
- ^self
- ]
- " Convert point into grid array index "
- idx: pt [ ^(pt y * (dims x + 1)) + pt x ]
- " Scan lines starting from start-end (by step), moving inc along then "
- scanFrom: start to: end by: step inc: inc [
- | vis pos curr next |
- vis := OrderedCollection new.
- (start to: end by: step) do: [ :p |
- pos := p.
- curr := grid at: (vis add: pos).
- [curr < $9 and: [(next := grid at: pos) ~= $#]] whileTrue: [
- (next > curr) ifTrue: [
- curr := next.
- vis add: pos
- ].
- pos := pos + inc
- ].
- ].
- ^vis
- ]
- scan [
- | vis |
- vis := Set new.
- " down "
- vis addAll: (self scanFrom: (self idx: 2 @ 1)
- to: (self idx: (dims x - 1) @ 1)
- by: (dirs at: #right)
- inc: (dirs at: #down)).
- " up "
- vis addAll: (self scanFrom: (self idx: 2 @ dims y)
- to: (self idx: (dims x - 1) @ dims y)
- by: (dirs at: #right)
- inc: (dirs at: #up)).
- " right "
- vis addAll: (self scanFrom: (self idx: 1 @ 2)
- to: (self idx: 1 @ (dims y - 1))
- by: (dirs at: #down)
- inc: (dirs at: #right)).
- " left "
- vis addAll: (self scanFrom: (self idx: dims x @ 2)
- to: (self idx: dims x @ (dims y - 1))
- by: (dirs at: #down)
- inc: (dirs at: #left)).
- ^vis
- ]
- viewFrom: loc at: height in: dir [
- | dist pos tree |
- dist := 0.
- pos := loc + dir.
- [(tree := grid at: pos) ~= $# and: [tree < height]] whileTrue: [
- dist := dist + 1.
- pos := pos + dir.
- ].
- " If we stop at a tree (instead of off the edge), count it: "
- ^dist + ((tree ~= $#) ifTrue: [1] ifFalse: [0])
- ]
- scenicView [
- | bestScore |
- bestScore := 0.
- ((self idx: 2 @ 2) to: (self idx: 2 @ dims y - 1) by: (dirs at: #down)) do: [ :start |
- (0 to: dims x - 2) do: [ :x |
- | loc pos height score |
- loc := start + x.
- height := grid at: loc.
- score := dirs inject: 1 into: [ :acc :dir |
- acc * (self viewFrom: loc at: height in: dir)
- ].
- bestScore := bestScore max: score.
- ]
- ].
- ^bestScore
- ]
- ]
- "
- | Mainline
- "
- grid := TreeGrid new: stdin lines contents.
- " Set of all visible, except the corners "
- visible := grid scan.
- ('Part 1: %1' % {visible size + 4}) displayNl.
- ('Part 2: %1' % {grid scenicView}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement