Advertisement
musifter

AoC 2021 day 15 (smalltalk)

Dec 15th, 2021
2,138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. Integer extend [
  4.     " Does number % N, but returns residue on interval of 1 to N, not 0 to N-1. "
  5.     %% modulus [ ^self - 1 \\ modulus + 1 ]
  6. ]
  7.  
  8. "
  9. | PriorityQueue implementation using SortedCollection for now
  10. "
  11. Object subclass: PriorityItem [
  12.     | priority data |
  13.  
  14.     PriorityItem class >> new: pri data: anArray [ ^super new init: pri data: anArray ]
  15.     init: pri data: array [ priority := pri. data := array. ^self ]
  16.  
  17.     <= state  [ ^self priority <= state priority ]
  18.     priority  [ ^priority ]
  19.     data      [ ^data     ]
  20. ]
  21.  
  22. SortedCollection subclass: PriorityQueue [
  23.     <shape: #pointer>
  24.  
  25.     PriorityQueue class >> new [ ^super new init ]
  26.     init  [ ^self ]
  27.  
  28.     at: pri insert: data  [ self add: (PriorityItem new: pri data: data) ]
  29.  
  30.     next      [ ^self removeFirst data ]
  31.     priority  [ ^self first priority   ]
  32. ]
  33.  
  34. "
  35. |  Class to handle the 2D Grid
  36. "
  37. Object subclass: DigitGrid [
  38.     | grid xsize ysize visit |
  39.  
  40.     dirs := { (-1@ 0). (0@-1). (0@ 1). (1@ 0) }.
  41.  
  42.     DigitGrid class >> new: arrayStrings [
  43.         ^(super new) init: arrayStrings.
  44.     ]
  45.  
  46.     init: mapArray [
  47.         | inx iny |
  48.         inx := (mapArray at: 1) size.
  49.         iny := mapArray size.
  50.  
  51.         xsize := inx * 5.
  52.         ysize := iny * 5.
  53.  
  54.         grid := (1 to: ysize) collect: [ :y | Array new: xsize ].
  55.  
  56.         (1 to: (mapArray at: 1) size) do: [ :y |
  57.             (1 to: mapArray size) do: [ :x |
  58.                 (grid at: y) at: x put: ((mapArray at: y) at: x) digitValue.
  59.             ]
  60.         ].
  61.  
  62.         (0 to: 4) do: [ :cy |
  63.             (0 to: 4) do: [ :cx |
  64.                 ((cy ~= 0) | (cx ~= 0)) ifTrue: [
  65.                     | inc |
  66.                     inc := cy + cx.
  67.                     (1 to: iny) do: [ :y |
  68.                         (1 to: inx) do: [ :x |
  69.                             (grid at: (iny * cy + y)) at: (inx * cx + x)
  70.                                   put: ((grid at: y) at: x) + inc %% 9.
  71.                         ]
  72.                     ]
  73.                 ]
  74.             ]
  75.         ].
  76.  
  77.         visit := (1 to: ysize) collect: [:i | Array new: xsize withAll: SmallInteger largest].
  78.         ^self
  79.     ]
  80.  
  81.     " Access to grid by Points "
  82.     at: pt  [ ^(grid at: pt y) at: pt x ]
  83.  
  84.     visited: pt         [ ^(visit at: pt y) at: pt x           ]
  85.     visit: pt at: risk  [ ^(visit at: pt y) at: pt x put: risk ]
  86.  
  87.     xsize  [ ^xsize ]
  88.     ysize  [ ^ysize ]
  89.  
  90.     " Get coordinates of neighbours "
  91.     neighbours: pt [
  92.         ^(dirs collect: [:d | pt + d ]) select: [:n |
  93.             (n x between: 1 and: xsize) & (n y between: 1 and: ysize)
  94.         ]
  95.     ]
  96.  
  97.     " For display "
  98.     printOn: aStream [
  99.         grid do: [ :i |
  100.             i printOn: aStream.
  101.             aStream nl.
  102.         ]
  103.     ]
  104. ]
  105.  
  106. "
  107. | Mainline
  108. "
  109. Eval [
  110.     grid := DigitGrid new: (stdin lines contents).
  111.  
  112.     queue := PriorityQueue new.
  113.     queue at: 0 insert: {0. 1 @ 1}.
  114.  
  115.     time := 0.
  116.  
  117.     [ queue notEmpty ] whileTrue: [
  118.         | state pos risk |
  119.         state := queue next.
  120.         risk  := state first.
  121.         pos   := state second.
  122.  
  123.         ((time := time + 1) \\ 50000 == 1) ifTrue: [
  124.             stderr nextPutAll: ('Risk: %1' % {risk}); cr; flush.
  125.         ].
  126.  
  127.         ((pos x == grid xsize) and: [pos y == grid ysize]) ifTrue: [
  128.             ^('Part 2: %1' % {risk}) displayNl.
  129.         ].
  130.  
  131.         ((grid visited: pos) > risk) ifTrue: [
  132.             grid visit: pos at: risk.
  133.  
  134.             (grid neighbours: pos) do: [ :move |
  135.                | new_risk |
  136.                 new_risk := risk + (grid at: move).
  137.                 queue at: new_risk insert: {new_risk. move}.
  138.             ]
  139.         ]
  140.     ]
  141. ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement