Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- Symbol extend [ value: arg [^arg perform: self] ]
- " Extend Point for mod and construction from an array: "
- Point extend [ \\ mod [^(self x \\ mod x) @ (self y \\ mod y)] ]
- Point class extend [ from: array [^array first @ array second] ]
- " Extend Collection for some basic stats: "
- Collection extend [
- product [ ^self inject: 1 into: [:a :b | a * b] ]
- mean [ ^(self fold: [:a :b | a + b]) / self size ]
- variance [
- | mean |
- mean := self mean.
- ^(self inject: 0 into: [:a :b | a + (b - mean) squared]) / self size
- ]
- ]
- " Structure class to hold Robot data, calculate position at time "
- Object subclass: Robot [
- | pos vel |
- dims := (101 @ 103).
- Robot class >> dims [^dims]
- Robot class >> pos: p vel: v [^super new initPos: p vel: v]
- initPos: p vel: v [pos := p. vel := v. ^self ]
- at: time [^(pos + (vel * time)) \\ dims]
- ]
- "
- | Mainline
- "
- " Convert each line into list of the two Points in it (pos and vel) "
- input := stdin lines contents collect: [:line |
- line substrings collect: [:word |
- Point from: (((word allButFirst: 2) substrings: $,) collect: #asNumber)
- ]
- ].
- robots := input collect: [:pt | Robot pos: (pt first) vel: (pt second)].
- " Variables for tracking smallest variances: "
- minX := -1. minY := -1.
- minVarX := SmallInteger largest.
- minVarY := SmallInteger largest.
- (0 to: (Robot dims x max: Robot dims y) - 1) do: [ :time |
- moved := robots collect: [:r | r at: time].
- (time == 100) ifTrue: [
- " Shift the origin to the middle, strip ones on the axes: "
- half := Robot dims // 2.
- shifted := (moved collect: [:pos | pos - half]) reject: [:p | (p x == 0) | (p y == 0)].
- " Collect the four quadrants in a Bag: "
- quads := Bag from: (shifted collect: [:pos | pos // (pos x abs @ pos y abs)]).
- ('Part 1: %1' % {quads contents values product}) displayNl.
- ].
- " Get minimum variance in each direction, and the interation % size (ASSUME primes) "
- varX := (moved collect: #x) variance.
- varY := (moved collect: #y) variance.
- (varX < minVarX) ifTrue: [minX := time. minVarX := varX].
- (varY < minVarY) ifTrue: [minY := time. minVarY := varY].
- ].
- " ASSUME: dimensions are prime so we can use Fermat's Little Theorem for this: "
- " a^(p-1) = 1 (mod p) => a^(p-2) is inverse "
- invMod := (Robot dims x) raisedToInteger: (Robot dims y - 2) \\ Robot dims y.
- ('Part 2: %1' % {minX + ((invMod * (minY - minX) \\ Robot dims y) * Robot dims x)}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement