This commit is contained in:
Beatrice Szilvasy 2024-12-14 12:28:42 +00:00
parent 6aba245667
commit 914f1d590b
2 changed files with 142 additions and 7 deletions

108
days/day14.st Normal file
View 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.

View file

@ -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}
]
] ]