Advertisement
musifter

AoC 2022, day 24 (smalltalk)

Dec 24th, 2022 (edited)
2,041
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 3.95 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. FileStream fileIn: '../../smalltalk/Priority.st'!
  4.  
  5. Point extend [
  6.     distance: pt [ ^(self x - pt x) abs + (self y - pt y) abs ]
  7. ]
  8.  
  9. Integer extend [
  10.     " Does number % N, but returns residue on interval of 1 to N, not 0 to N-1. "
  11.     %% modulus [ ^self - 1 \\ modulus + 1 ]
  12. ]
  13.  
  14. Object subclass: Valley [
  15.     | dim grid start end vBlizz hBlizz |
  16.  
  17.     dirs := { (1@0). (-1@0). (0@1). (0@-1). (0@0) }.
  18.  
  19.     Valley class >> new: textArray [
  20.         ^super new init: textArray
  21.     ]
  22.  
  23.     init: arr [
  24.         | blizz sentinel |
  25.         dim := (arr first size) @ (arr size).
  26.  
  27.         " Build flattened array version of grid with sentinels "
  28.         sentinel := String new.
  29.         dim x timesRepeat: [ sentinel := sentinel, '#' ].
  30.         grid := sentinel, arr join, sentinel.
  31.  
  32.         " Break input into list of coordinates for each character "
  33.         blizz := Dictionary new.
  34.         (1 to: dim y) do: [ :y |
  35.             (1 to: dim x) do: [ :x |
  36.                 (blizz at: ((arr at: y) at: x) ifAbsentPut: [OrderedCollection new]) add: (x@y)
  37.             ].
  38.         ].
  39.         stdout nextPutAll: 'Gathered blizzards...'; nl; flush.
  40.  
  41.         " Find start and end positions "
  42.         start := (blizz at: $.) detect: [:pt | pt y = 1].
  43.         end   := (blizz at: $.) detect: [:pt | pt y = arr size].
  44.  
  45.         stdout nextPutAll: 'Building vertical table...'; nl; flush.
  46.         vBlizz := (1 to: dim y - 2) collect: [:x | Set new].
  47.         (0 to: dim y - 3) do: [ :time |
  48.            | vb |
  49.             vb := vBlizz at: time + 1.
  50.             vb addAll: ((blizz at: $^) collect: [:pt | pt x @ ((pt y - time - 1) %% (dim y - 2) + 1)]).
  51.             vb addAll: ((blizz at: $v) collect: [:pt | pt x @ ((pt y + time - 1) %% (dim y - 2) + 1)]).
  52.         ].
  53.  
  54.         hBlizz := (1 to: dim x - 2) collect: [:x | Set new].
  55.         (0 to: dim x - 3) do: [ :time |
  56.            | hb |
  57.             hb := hBlizz at: time + 1.
  58.             hb addAll: ((blizz at: $<) collect: [:pt | ((pt x - time - 1) %% (dim x - 2) + 1) @ pt y]).
  59.             hb addAll: ((blizz at: $>) collect: [:pt | ((pt x + time - 1) %% (dim x - 2) + 1) @ pt y]).
  60.         ].
  61.         ^self
  62.     ]
  63.  
  64.     clear: pt at: time [
  65.         | blizz |
  66.         blizz := ((vBlizz at: (time + 1) %% (dim y - 2)) includes: pt)
  67.                     or: [(hBlizz at: (time + 1) %% (dim x - 2)) includes: pt].
  68.  
  69.         ^blizz not and: [(grid at: (pt y * dim x + pt x)) ~= $#]
  70.     ]
  71.  
  72.     from: startPos to: endPos begin: startTime [
  73.         | queue visit key dist count state time pos |
  74.         visit := Set new.
  75.         count := 0.
  76.  
  77.         queue := PriorityQueue new.
  78.         queue at: 0 insert: {startTime. startPos}.
  79.  
  80.         [ (state := queue next) notNil ] whileTrue: [
  81.             time := state first.
  82.             pos  := state second.
  83.  
  84.             ((count := count + 1) \\ 1000) = 0 ifTrue: [
  85.                 stderr nextPutAll: ('[%1] %2   ' % {time. pos}); cr; flush.
  86.             ].
  87.  
  88.             (pos = endPos) ifTrue: [ ^time - 1 ].
  89.  
  90.             key := time asString, ':', pos printString.
  91.             (visit includes: key) ifFalse: [
  92.                 visit add: key.
  93.  
  94.                 (dirs collect: [:d | pos + d]) do: [ :neigh |
  95.                     (self clear: neigh at: time) ifTrue: [
  96.                         dist := neigh distance: endPos.
  97.                         queue at: (time + 1 + dist) insert: {time + 1. neigh}.
  98.                     ].
  99.                 ].
  100.             ]
  101.         ]
  102.     ]
  103.  
  104.     dim     [ ^dim   ]
  105.     start   [ ^start ]
  106.     end     [ ^end   ]
  107. ]
  108.  
  109. "
  110. | Mainline
  111. "
  112. ObjectMemory spaceGrowRate: 500.0.
  113.  
  114. valley := Valley new: stdin lines contents.
  115. stdout nextPutAll: 'Loaded.'; nl; flush.
  116.  
  117. time := valley from: valley start to: valley end begin: 0.
  118. ('Part 1: %1  ' % {time}) displayNl.
  119.  
  120. time := valley from: valley end   to: valley start begin: time.
  121. time := valley from: valley start to: valley end   begin: time.
  122. ('Part 2: %1  ' % {time}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement