Day 14
This commit is contained in:
parent
6aba245667
commit
914f1d590b
2 changed files with 142 additions and 7 deletions
108
days/day14.st
Normal file
108
days/day14.st
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
Object subclass: Robot [
|
||||
| pos vel |
|
||||
parse: line
|
||||
[ line scanf: 'p=%d,%d v=%d,%d' with: [
|
||||
:px :py :vx :vy |
|
||||
pos := Posn x: px y: py.
|
||||
vel := Posn x: vx y: vy ]]
|
||||
|
||||
printOn: st [ st << '{p=' << pos << ' v=' << vel << '}' ]
|
||||
|
||||
posAt: time in: br
|
||||
[ ^Posn
|
||||
x: (pos x + (vel x * (time \\ br w))) \\ br w
|
||||
y: (pos y + (vel y * (time \\ br h))) \\ br h ]
|
||||
]
|
||||
|
||||
Array extend [
|
||||
incAt: pos [ self at: pos put: 1 + (self at: pos) ]
|
||||
]
|
||||
|
||||
Posn subclass: Bathroom [
|
||||
| midx midy |
|
||||
w [^x] h [^y]
|
||||
|
||||
x: n [super x: n. midx := x // 2]
|
||||
y: n [super y: n. midy := y // 2]
|
||||
|
||||
countQuadrants: posns
|
||||
[ | qs |
|
||||
qs := Array new: 4 withAll: 0.
|
||||
posns do: [ :p | self putPosn: p toQuad: qs ].
|
||||
^qs inject: 1 into: [:l :r | l * r] ]
|
||||
|
||||
putPosn: p toQuad: qs
|
||||
[ | top bot |
|
||||
top := p y < midy.
|
||||
bot := p y > midy.
|
||||
p x < midx ifTrue:
|
||||
[ top ifTrue: [^qs incAt: 1].
|
||||
bot ifTrue: [^qs incAt: 2].
|
||||
^nil ].
|
||||
p x > midx ifTrue:
|
||||
[ top ifTrue: [^qs incAt: 3].
|
||||
bot ifTrue: [^qs incAt: 4].
|
||||
^nil ] ]
|
||||
|
||||
findMaxOf: robots inPeriod: p withTrue: filter
|
||||
[ | best bestTime |
|
||||
best := -1.
|
||||
1 to: p do: [
|
||||
:time | | cnt |
|
||||
cnt := robots count: [:it | filter value: (it posAt: time in: self)].
|
||||
cnt > best ifTrue: [best := cnt. bestTime := time] ].
|
||||
^bestTime ]
|
||||
|
||||
plot: robots at: time
|
||||
[ | grid orig |
|
||||
grid := 1 to: self h collect: [:i | String new: self w withAll: $.].
|
||||
grid := Grid new rows: grid.
|
||||
orig := Posn x: 1 y: 1.
|
||||
robots do: [:r | grid at: orig + (r posAt: time in: self) put: $#].
|
||||
stdout << 'At ' << time << ':'; nl; << grid; nl; nl. ]
|
||||
|
||||
betweenPercentile: min and: max by: getKey
|
||||
[ | mine minV maxV |
|
||||
mine := getKey value: self.
|
||||
minV := mine * min.
|
||||
maxV := mine * max.
|
||||
^[ :it | | its | its := getKey value: it.
|
||||
minV <= its and: [its <= maxV] ] ]
|
||||
|
||||
inMiddleBy: getKey
|
||||
[ ^self betweenPercentile: 0.4 and: 0.6 by: getKey ]
|
||||
|
||||
findMaxRobots: robots inMiddleBy: getKey
|
||||
[ ^self findMaxOf: robots
|
||||
inPeriod: (getKey value: self)
|
||||
withTrue: (self inMiddleBy: getKey) ]
|
||||
|
||||
findTreeTimeOf: robots
|
||||
[ | bestx besty |
|
||||
"The tree is a little pictogram in the center of the image -- we
|
||||
find the offset with which the robots condense here on both the
|
||||
X and Y axes, then use CRT to compute where these coincide."
|
||||
bestx := self findMaxRobots: robots inMiddleBy: [:it | it x].
|
||||
besty := self findMaxRobots: robots inMiddleBy: [:it | it y].
|
||||
|
||||
(self w gcd: self h) = 1 ifFalse: [self error: 'Not coprime'].
|
||||
^(self w egcd: self h) letArrayInBlock:
|
||||
[ :cx :cy |
|
||||
(bestx * cy * self h)
|
||||
+ (besty * cx * self w)
|
||||
\\ (self w * self h) ] ]
|
||||
]
|
||||
|
||||
Bathroom class extend [
|
||||
width: w height: h [^self x: w y: h]
|
||||
]
|
||||
|
||||
theBathroom := Bathroom width: 101 height: 103.
|
||||
|
||||
AOC input: [ stdin toLines asArray collect: [ :it | Robot new parse: it ] ];
|
||||
part1: [ :robots | | posns |
|
||||
posns := robots collect: [:it | it posAt: 100 in: theBathroom].
|
||||
theBathroom countQuadrants: posns ];
|
||||
part2: [ :robots | theBathroom findTreeTimeOf: robots ];
|
||||
result: [ :robots :part | part value: robots. ];
|
||||
finish.
|
||||
|
|
@ -74,11 +74,15 @@ Object subclass: ScannerState [
|
|||
finish [ ^oc asArray ]
|
||||
|
||||
parseIntOn: stream
|
||||
[ | d |
|
||||
d := 0.
|
||||
[ | d sf c |
|
||||
d := 0. sf := 1. c := stream peek.
|
||||
(c = $+) | (c = $-) ifTrue: [
|
||||
stream next.
|
||||
c = $- ifTrue: [sf := -1]
|
||||
].
|
||||
stream whilePeek: [ :c | c isDigit ] do:
|
||||
[ :c | d := d * 10 + c digitValue ].
|
||||
oc add: d ]
|
||||
oc add: (sf * d) ]
|
||||
|
||||
parseStringOn: stream
|
||||
[ | s | s := OrderedCollection new.
|
||||
|
|
@ -224,7 +228,7 @@ Object subclass: Posn [
|
|||
printOn: s [ s << '<' << x << ', ' << y << '>'. ]
|
||||
]
|
||||
Posn class extend [
|
||||
x: x y: y [ ^Posn new x: x; y: y ]
|
||||
x: x y: y [ ^self new x: x; y: y ]
|
||||
up: n [ ^Posn x: 0 y: n negated ]
|
||||
down: n [ ^Posn x: 0 y: n ]
|
||||
left: n [ ^Posn x: n negated y: 0 ]
|
||||
|
|
@ -272,7 +276,9 @@ Array extend [ asPosn [ ^Posn x: (self at: 1) y: (self at: 2) ] ]
|
|||
Iterable extend [ asPosns [ ^self collect: [:it | it asPosn] ] ]
|
||||
|
||||
Object subclass: Grid [
|
||||
| rows | rows: n [rows:=n]
|
||||
| rows |
|
||||
rows: n [rows:=n]
|
||||
rows [^rows]
|
||||
|
||||
at: pos [ ^(rows at: pos y ifAbsent: [^nil]) at: pos x ifAbsent: [nil] ]
|
||||
at: pos put: elt
|
||||
|
|
@ -319,9 +325,12 @@ Dictionary extend [
|
|||
]
|
||||
|
||||
Integer extend [
|
||||
ceilingDiv: denom [ ^((self - 1) // denom) + 1 ]
|
||||
ceilingDiv: denom [
|
||||
"Answer (self / denom) ceiling."
|
||||
^((self - 1) // denom) + 1
|
||||
]
|
||||
|
||||
"The original implementation was incorrect. Here is the correct code:"
|
||||
"Original code was incorrect:"
|
||||
ceilingLog: radix [
|
||||
"Answer (self log: radix) ceiling. Optimized to answer an integer."
|
||||
|
||||
|
|
@ -343,4 +352,22 @@ Integer extend [
|
|||
answer := answer + 1].
|
||||
^answer
|
||||
]
|
||||
|
||||
egcd: o [
|
||||
"Answer {x . y} such that (self * x) + (o * y) = (self gcd: o)."
|
||||
| q r0 r s0 s t0 t tmp |
|
||||
r0 := self. r := o.
|
||||
s0 := 1. s := 0.
|
||||
t0 := 0. t := 1.
|
||||
|
||||
[r ~= 0] whileTrue: [
|
||||
q := r0 // r.
|
||||
|
||||
tmp := r. r := r0 - (q * r). r0 := tmp.
|
||||
tmp := s. s := s0 - (q * s). s0 := tmp.
|
||||
tmp := t. t := t0 - (q * t). t0 := tmp.
|
||||
].
|
||||
|
||||
^{s0 . t0}
|
||||
]
|
||||
]
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue