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 ]
|
finish [ ^oc asArray ]
|
||||||
|
|
||||||
parseIntOn: stream
|
parseIntOn: stream
|
||||||
[ | d |
|
[ | d sf c |
|
||||||
d := 0.
|
d := 0. sf := 1. c := stream peek.
|
||||||
|
(c = $+) | (c = $-) ifTrue: [
|
||||||
|
stream next.
|
||||||
|
c = $- ifTrue: [sf := -1]
|
||||||
|
].
|
||||||
stream whilePeek: [ :c | c isDigit ] do:
|
stream whilePeek: [ :c | c isDigit ] do:
|
||||||
[ :c | d := d * 10 + c digitValue ].
|
[ :c | d := d * 10 + c digitValue ].
|
||||||
oc add: d ]
|
oc add: (sf * d) ]
|
||||||
|
|
||||||
parseStringOn: stream
|
parseStringOn: stream
|
||||||
[ | s | s := OrderedCollection new.
|
[ | s | s := OrderedCollection new.
|
||||||
|
|
@ -224,7 +228,7 @@ Object subclass: Posn [
|
||||||
printOn: s [ s << '<' << x << ', ' << y << '>'. ]
|
printOn: s [ s << '<' << x << ', ' << y << '>'. ]
|
||||||
]
|
]
|
||||||
Posn class extend [
|
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 ]
|
up: n [ ^Posn x: 0 y: n negated ]
|
||||||
down: n [ ^Posn x: 0 y: n ]
|
down: n [ ^Posn x: 0 y: n ]
|
||||||
left: n [ ^Posn x: n negated y: 0 ]
|
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] ] ]
|
Iterable extend [ asPosns [ ^self collect: [:it | it asPosn] ] ]
|
||||||
|
|
||||||
Object subclass: Grid [
|
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 [ ^(rows at: pos y ifAbsent: [^nil]) at: pos x ifAbsent: [nil] ]
|
||||||
at: pos put: elt
|
at: pos put: elt
|
||||||
|
|
@ -319,9 +325,12 @@ Dictionary extend [
|
||||||
]
|
]
|
||||||
|
|
||||||
Integer 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 [
|
ceilingLog: radix [
|
||||||
"Answer (self log: radix) ceiling. Optimized to answer an integer."
|
"Answer (self log: radix) ceiling. Optimized to answer an integer."
|
||||||
|
|
||||||
|
|
@ -343,4 +352,22 @@ Integer extend [
|
||||||
answer := answer + 1].
|
answer := answer + 1].
|
||||||
^answer
|
^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