Advertisement
musifter

AoC 2024, day 14 (smalltalk)

Dec 14th, 2024
58
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Smalltalk 2.63 KB | Source Code | 0 0
  1. #!/usr/local/bin/gst -q
  2.  
  3. Symbol extend       [ value: arg  [^arg perform: self] ]
  4.  
  5. " Extend Point for mod and construction from an array: "
  6. Point extend        [ \\ mod  [^(self x \\ mod x) @ (self y \\ mod y)] ]
  7. Point class extend  [ from: array  [^array first @ array second] ]
  8.  
  9. " Extend Collection for some basic stats: "
  10. Collection extend [
  11.     product [ ^self inject: 1 into: [:a :b | a * b] ]
  12.  
  13.     mean    [ ^(self fold: [:a :b | a + b]) / self size ]
  14.     variance [
  15.         | mean |
  16.         mean := self mean.
  17.         ^(self inject: 0 into: [:a :b | a + (b - mean) squared]) / self size
  18.     ]
  19. ]
  20.  
  21. " Structure class to hold Robot data, calculate position at time "
  22. Object subclass: Robot [
  23.     | pos vel |
  24.     dims := (101 @ 103).
  25.     Robot class >> dims  [^dims]
  26.  
  27.     Robot class >> pos: p vel: v  [^super new initPos: p vel: v]
  28.     initPos: p vel: v             [pos := p.  vel := v.  ^self ]
  29.  
  30.     at: time  [^(pos + (vel * time)) \\ dims]
  31. ]
  32.  
  33. "
  34. | Mainline
  35. "
  36. " Convert each line into list of the two Points in it (pos and vel) "
  37. input := stdin lines contents collect: [:line |
  38.              line substrings collect: [:word |
  39.                  Point from: (((word allButFirst: 2) substrings: $,) collect: #asNumber)
  40.              ]
  41.          ].
  42.  
  43. robots := input collect: [:pt | Robot pos: (pt first) vel: (pt second)].
  44.  
  45. " Variables for tracking smallest variances: "
  46. minX := -1. minY := -1.
  47. minVarX := SmallInteger largest.
  48. minVarY := SmallInteger largest.
  49.  
  50. (0 to: (Robot dims x max: Robot dims y) - 1) do: [ :time |
  51.     moved := robots collect: [:r | r at: time].
  52.  
  53.     (time == 100) ifTrue: [
  54.         " Shift the origin to the middle, strip ones on the axes: "
  55.         half    := Robot dims // 2.
  56.         shifted := (moved collect: [:pos | pos - half]) reject: [:p | (p x == 0) | (p y == 0)].
  57.  
  58.         " Collect the four quadrants in a Bag: "
  59.         quads   := Bag from: (shifted collect: [:pos | pos // (pos x abs @ pos y abs)]).
  60.  
  61.         ('Part 1: %1' % {quads contents values product}) displayNl.
  62.     ].
  63.  
  64.     " Get minimum variance in each direction, and the interation % size (ASSUME primes) "
  65.     varX := (moved collect: #x) variance.
  66.     varY := (moved collect: #y) variance.
  67.  
  68.     (varX < minVarX) ifTrue: [minX := time. minVarX := varX].
  69.     (varY < minVarY) ifTrue: [minY := time. minVarY := varY].
  70. ].
  71.  
  72. " ASSUME: dimensions are prime so we can use Fermat's Little Theorem for this: "
  73. " a^(p-1) = 1 (mod p)  => a^(p-2) is inverse "
  74. invMod := (Robot dims x) raisedToInteger: (Robot dims y - 2) \\ Robot dims y.
  75.  
  76. ('Part 2: %1' % {minX + ((invMod * (minY - minX) \\ Robot dims y) * Robot dims x)}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement