Advertisement
musifter

AoC 2022, day 8 (smalltalk)

Dec 8th, 2022
2,174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 3.75 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. " Uses a flat array (String) for the grid, with sentinel #s inserted "
  4. Object subclass: TreeGrid [
  5.     | grid dims dirs |
  6.  
  7.     TreeGrid class >> new: textArray [
  8.         ^super new init: textArray
  9.     ]
  10.  
  11.     init: textArray [
  12.         | sent |
  13.         dims := (textArray at: 1) size @ textArray size.
  14.  
  15.         " Flatten and add sentinel rows to top. bottom, and between rows "
  16.         sent := (1 to: dims x + 1) inject: '' into: [:a :b | a, '#'].
  17.         grid := sent, (textArray collect: [:x | x, '#']) join, sent.
  18.  
  19.         dirs := Dictionary from: {
  20.                     #right ->  1.
  21.                     #left  -> -1.
  22.                     #down  -> (dims x + 1).
  23.                     #up    -> (dims x + 1) negated.
  24.                 }.
  25.         ^self
  26.     ]
  27.  
  28.     " Convert point into grid array index "
  29.     idx: pt  [ ^(pt y * (dims x + 1)) + pt x ]
  30.  
  31.     " Scan lines starting from start-end (by step), moving inc along then "
  32.     scanFrom: start to: end by: step inc: inc [
  33.         | vis pos curr next |
  34.         vis := OrderedCollection new.
  35.  
  36.         (start to: end by: step) do: [ :p |
  37.             pos  := p.
  38.             curr := grid at: (vis add: pos).
  39.  
  40.             [curr < $9 and: [(next := grid at: pos) ~= $#]] whileTrue: [
  41.                 (next > curr) ifTrue: [
  42.                     curr := next.
  43.                     vis add: pos
  44.                 ].
  45.                 pos := pos + inc
  46.             ].
  47.         ].
  48.         ^vis
  49.     ]
  50.  
  51.     scan [
  52.         | vis |
  53.         vis := Set new.
  54.  
  55.         " down "
  56.         vis addAll: (self scanFrom: (self idx: 2 @ 1)
  57.                                 to: (self idx: (dims x - 1) @ 1)
  58.                                 by: (dirs at: #right)
  59.                                inc: (dirs at: #down)).
  60.  
  61.         " up "
  62.         vis addAll: (self scanFrom: (self idx: 2 @ dims y)
  63.                                 to: (self idx: (dims x - 1) @ dims y)
  64.                                 by: (dirs at: #right)
  65.                                inc: (dirs at: #up)).
  66.  
  67.         " right "
  68.         vis addAll: (self scanFrom: (self idx: 1 @ 2)
  69.                                 to: (self idx: 1 @ (dims y - 1))
  70.                                 by: (dirs at: #down)
  71.                                inc: (dirs at: #right)).
  72.  
  73.         " left "
  74.         vis addAll: (self scanFrom: (self idx: dims x @ 2)
  75.                                 to: (self idx: dims x @ (dims y - 1))
  76.                                 by: (dirs at: #down)
  77.                                inc: (dirs at: #left)).
  78.         ^vis
  79.     ]
  80.  
  81.     viewFrom: loc at: height in: dir [
  82.         | dist pos tree |
  83.         dist := 0.
  84.         pos  := loc + dir.
  85.  
  86.         [(tree := grid at: pos) ~= $# and: [tree < height]] whileTrue: [
  87.             dist := dist + 1.
  88.             pos := pos + dir.
  89.         ].
  90.  
  91.         " If we stop at a tree (instead of off the edge), count it: "
  92.         ^dist + ((tree ~= $#) ifTrue: [1] ifFalse: [0])
  93.     ]
  94.  
  95.     scenicView [
  96.         | bestScore |
  97.         bestScore := 0.
  98.  
  99.         ((self idx: 2 @ 2) to: (self idx: 2 @ dims y - 1) by: (dirs at: #down)) do: [ :start |
  100.             (0 to: dims x - 2) do: [ :x |
  101.                | loc pos height score |
  102.                 loc    := start + x.
  103.                 height := grid at: loc.
  104.  
  105.                 score := dirs inject: 1 into: [ :acc :dir |
  106.                              acc * (self viewFrom: loc at: height in: dir)
  107.                          ].
  108.  
  109.                 bestScore := bestScore max: score.
  110.             ]
  111.         ].
  112.         ^bestScore
  113.     ]
  114. ]
  115.  
  116. "
  117. | Mainline
  118. "
  119. grid := TreeGrid new: stdin lines contents.
  120.  
  121. " Set of all visible, except the corners "
  122. visible := grid scan.
  123. ('Part 1: %1' % {visible size + 4}) displayNl.
  124. ('Part 2: %1' % {grid scenicView}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement