Advertisement
musifter

AoC 2022, day 17 (smalltalk pt 2)

Dec 17th, 2022 (edited)
2,439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 4.18 KB | Source Code | 0 0
  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. Object subclass: MoveStream [
  9.     | buff idx |
  10.  
  11.     dirs := Dictionary from: {$> -> (1 @ 0). $< -> (-1 @ 0)}.
  12.  
  13.     MoveStream class >> new: input [ ^super new init: input ]
  14.  
  15.     init: input  [ buff := input. idx := 0. ^self ]
  16.     index        [ ^idx ]
  17.     next         [ ^dirs at: (buff at: (idx := (idx + 1) %% buff size)) ]
  18. ]
  19.  
  20. Object subclass: BlockStream [
  21.     | idx |
  22.     blocks := {{0@0. 1@0. 2@0. 3@0}.
  23.                {1@0. 0@1. 1@1. 2@1. 1@2}.
  24.                {0@0. 1@0. 2@0. 2@1. 2@2}.
  25.                {0@0. 0@1. 0@2. 0@3}.
  26.                {0@0. 1@0. 0@1. 1@1}}.
  27.  
  28.     BlockStream class >> new [ ^super new init ]
  29.  
  30.     init    [ idx := 0. ^self ]
  31.     index   [ ^idx ]
  32.  
  33.     nextPos: pos [
  34.         idx := (idx + 1) %% blocks size.
  35.         ^(blocks at: idx) collect: [:sq | sq + pos].
  36.     ]
  37. ]
  38.  
  39. Object subclass: Shaft [
  40.     | grid top height |
  41.  
  42.     Shaft class >> new: max [ ^super new init: max ]
  43.  
  44.     init: max [
  45.         grid   := Array new: max withAll: 0.
  46.         height := Array new: max.
  47.         top    := 0.
  48.         ^self
  49.     ]
  50.  
  51.     top  [ ^top ]
  52.  
  53.     recordHeight: rock [ ^height at: rock put: top ]
  54.     heightAt: rock     [ ^height at: rock          ]
  55.  
  56.     at: pt [
  57.         ^(grid at: pt y) bitAnd: (1 bitShift: pt x).
  58.     ]
  59.  
  60.     mark: pt [
  61.         top := top max: pt y.
  62.         ^grid at: pt y put: ((grid at: pt y) bitOr: (1 bitShift: pt x))
  63.     ]
  64.  
  65.     hashString [
  66.         | ret mask row |
  67.         ret  := String new.
  68.  
  69.         mask := 0.
  70.         row  := top.
  71.         [row > 0 and: [mask < 127]] whileTrue: [
  72.             | curr |
  73.             curr := grid at: row.
  74.             ret  := ret, curr asCharacter asString.
  75.             mask := mask bitOr: curr.
  76.             row  := row - 1.
  77.         ].
  78.         ^ret
  79.     ]
  80.  
  81.     printOn: aStream [
  82.         (top to: 1 by: -1) do: [:y |
  83.             aStream nextPut: $|.
  84.             (0 to: 6) do: [:x |
  85.                 aStream nextPut: ((self at: x @ y) ~= 0 ifTrue:  [$#]
  86.                                                         ifFalse: [$.]).
  87.             ].
  88.             aStream nextPut: $|; nl.
  89.         ].
  90.         aStream nextPutAll: '+-------+'; nl.
  91.     ]
  92. ]
  93.  
  94. "
  95. | Mainline
  96. "
  97. Eval [
  98.     num_rocks := 1_000_000_000_000.
  99.  
  100.     input  := MoveStream  new: stdin nextLine.
  101.     blocks := BlockStream new.
  102.     shaft  := Shaft new: 1_000_000.  " Should repeat well before this "
  103.     hash   := Dictionary new.
  104.  
  105.     rock := 0.
  106.     num_rocks timesRepeat: [         " again, should stop well before this "
  107.         dropped := true.
  108.  
  109.         " Get next block "
  110.         rock  := rock + 1.
  111.         block := blocks nextPos: 2 @ (shaft top + 4).
  112.  
  113.         [ dropped ] whileTrue: [
  114.             " Try shifting by move "
  115.             move := input next.
  116.             try := block collect: [:pt | pt + move].
  117.             (try conform: [:pt | (pt x between: 0 and: 6) and: [(shaft at: pt) = 0]]) ifTrue: [
  118.                 block := try.
  119.             ].
  120.  
  121.             " Try dropping down "
  122.             try := block collect: [:pt | pt + (0 @ -1)].
  123.             (dropped := try conform: [:pt | (pt y > 0) and: [(shaft at: pt) = 0]]) ifTrue: [
  124.                 block := try.
  125.             ].
  126.         ].
  127.  
  128.         " Place block "
  129.         block do: [:pt | shaft mark: pt].
  130.         shaft recordHeight: rock.
  131.  
  132.         " key is input&block pos, as well as top of shaft up until full width covered "
  133.         key := input index asString, ':', blocks index asString, ':', shaft hashString.
  134.         (hash includesKey: key) ifFalse: [
  135.             hash at: key put: {rock. shaft top}.
  136.         ] ifTrue: [
  137.             " Found loop: "
  138.             prev := hash at: key.
  139.  
  140.             lenCycle    := rock - prev first.
  141.             heightDelta := shaft top - prev second.
  142.  
  143.             numCycles := (num_rocks - rock) // lenCycle.
  144.             modCycle  := (num_rocks - rock) \\ lenCycle.
  145.  
  146.             extra := (shaft heightAt: (prev first + modCycle)) - prev second.
  147.             ^('Part 2: %1' % {shaft top + (numCycles * heightDelta) + extra}) displayNl.
  148.         ]
  149.     ]
  150. ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement