Advertisement
musifter

AoC 2022 day 12 (smalltalk)

Dec 12th, 2022
2,954
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 2.99 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. Collection extend [
  4.     apply: method  [ ^self collect: [:x | x perform: method] ]
  5. ]
  6.  
  7. Object subclass: HeightMap [
  8.     | grid start end |
  9.  
  10.     dirs := { 0 @ 1. 0 @ -1. 1 @ 0. -1 @ 0 }.
  11.  
  12.     HeightMap class >> new: arrayStrings [
  13.         ^super new init: arrayStrings
  14.     ]
  15.  
  16.     init: mapArray [
  17.         | width |
  18.         width := (mapArray at: 1) size + 2.
  19.  
  20.         grid := OrderedCollection new.
  21.         mapArray keysAndValuesDo: [ :y :line |
  22.            | row x |
  23.             row := line asOrderedCollection apply: #asInteger.
  24.             row addFirst: 128; addLast: 128.    " Add sentinels left/right "
  25.  
  26.             " Find start "
  27.             (x := row indexOf: $S asInteger) ~= 0 ifTrue: [
  28.                 start := x @ (y + 1).
  29.                 row at: x put: $a asInteger.
  30.             ].
  31.  
  32.             " Find end "
  33.             (x := row indexOf: $E asInteger) ~= 0 ifTrue: [
  34.                 end := x @ (y + 1).
  35.                 row at: x put: $z asInteger.
  36.             ].
  37.  
  38.             grid add: row asArray.
  39.         ].
  40.  
  41.         " Add sentinel rows to top and bottom "
  42.         grid addFirst: (Array new: width withAll: 128).
  43.         grid addLast:  (Array new: width withAll: 128).
  44.         ^self
  45.     ]
  46.  
  47.     at: pt  [ ^(grid at: pt y) at: pt x ]
  48.  
  49.     start   [ ^start ]
  50.     end     [ ^end   ]
  51.  
  52.     " Find path from startPos until endBlock is true, with heightAllow rule "
  53.     pathFrom: startPos endWhen: endBlock moving: heightAllow [
  54.         | visit queue state time pos height move |
  55.  
  56.         " Initialise visit array "
  57.         visit := (1 to: grid size) collect: [ :i |
  58.             Array new: (grid at: 1) size withAll: false
  59.         ].
  60.  
  61.         " Queue starts with startPos at time 0 "
  62.         queue := OrderedCollection with: { 0. startPos }.
  63.  
  64.         " Basic BFS loop: "
  65.         [ queue notEmpty ] whileTrue: [
  66.             state := queue removeFirst.
  67.             time  := state first.
  68.             pos   := state second.
  69.  
  70.             (endBlock value: pos) ifTrue: [ ^time ].
  71.  
  72.             ((visit at: pos y) at: pos x) ifFalse: [
  73.                 (visit at: pos y) at: pos x put: true.
  74.  
  75.                 height := self at: pos.
  76.                 dirs do: [ :dir |
  77.                     move := pos + dir.
  78.                     (heightAllow value: height value: (self at: move)) ifTrue: [
  79.                         queue addLast: { time + 1. move }.
  80.                     ]
  81.                 ]
  82.             ]
  83.         ]
  84.     ]
  85. ]
  86.  
  87. "
  88. | Mainline
  89. "
  90. map := HeightMap new: stdin lines contents.
  91.  
  92. " Start to end, going up: "
  93. part1 := map pathFrom: map start
  94.               endWhen: [:pos | pos = map end]
  95.                moving: [:height :targ | (height + 1) >= targ].
  96.  
  97. ('Part 1: %1' % {part1}) displayNl.
  98.  
  99. " End to level $a, going down: "
  100. part2 := map pathFrom: map end
  101.               endWhen: [:pos | (map at: pos) = $a asInteger]
  102.                moving: [:height :targ | targ between: (height - 1) and: $z asInteger].
  103.  
  104. ('Part 2: %1' % {part2}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement