This commit is contained in:
Beatrice Szilvasy 2024-12-25 08:09:23 +00:00
parent b3ebcbd041
commit eb829e8986
3 changed files with 110 additions and 73 deletions

View file

@ -114,79 +114,6 @@ Object subclass: Racetrack [
block value: dpos value: ddist ] asSpreader ] block value: dpos value: ddist ] asSpreader ]
] ]
Object subclass: KDTree [
from: min to: max do: block
[ self subclassResponsibility ]
]
KDTree class extend [
fromPoints: points
[ ^self fromShuffledPoints: (Random new shuffle: points asArray) ]
fromShuffledPoints: points
[ ^self fromShuffledPoints: points axis: 1 ]
leafMaxSize [ ^5 ]
fromShuffledPoints: points axis: ax
[ | med splits dims nextAx value |
points size <= self leafMaxSize ifTrue: [^KDLeaf new points: points asArray].
med := self guessMedian: points axis: ax.
dims := med size.
nextAx := ax \\ dims + 1.
value := med at: ax.
splits := self splitPoints: points axis: ax on: value.
^KDInner new
left: (self fromShuffledPoints: (splits at: 1) axis: nextAx)
right: (self fromShuffledPoints: (splits at: 2) axis: nextAx)
axis: ax
value: value ]
splitPoints: points axis: ax on: val
[ | l r fairLeft |
l := OrderedCollection new.
r := OrderedCollection new.
fairLeft := true.
points do: [
:point | | v onLeft |
v := point at: ax.
onLeft := (v < val) or: [
v = val and: [fairLeft := fairLeft not. fairLeft]].
(onLeft ifTrue: [l] ifFalse: [r]) add: point ].
^{l . r} ]
medianGuessSize [ ^5 ]
guessMedian: points axis: ax
[ | arr |
arr := 1 to: (points size min: self medianGuessSize)
collect: [:i | points at: i].
arr sort: [:l :r | (l at: ax) <= (r at: ax)].
^arr at: arr size // 2 + 1 ]
]
KDTree subclass: KDLeaf [
| points |
points: n [points := n. "self class leafSize: points size"]
from: min to: max do: block [ points do: block ]
printOn: st [ st << 'lf' << points ]
]
KDLeaf class extend [
| leafSizes |
leafSizes [ ^leafSizes ifNil: [leafSizes := Bag new] ]
leafSize: sz [ self leafSizes add: sz ]
]
KDTree subclass: KDInner [
| left right axis value |
left: l right: r axis: ax value: v
[left:=l. right:=r. axis:=ax. value:=v]
from: min to: max do: block
[ (min at: axis) <= value ifTrue: [ left from: min to: max do: block ].
(max at: axis) >= value ifTrue: [ right from: min to: max do: block ] ]
printOn: st [ st << '{' << left << ' <= [' << axis << '] '
<< value << ' <= ' << right << '}' ]
]
AOC input: [ Racetrack new rows: stdin toLines asArray ]; AOC input: [ Racetrack new rows: stdin toLines asArray ];
part1: 2; part2: 20; part1: 2; part2: 20;
result: [ :track :time | track countCheatsWithTime: time ]; result: [ :track :time | track countCheatsWithTime: time ];

36
days/day25.st Normal file
View file

@ -0,0 +1,36 @@
Object subclass: KeyOrLock [
| isLock height value |
value [^value]
isLock [^isLock]
rows: r
[ | cols |
cols := r lines transposed.
isLock := cols allSatisfy: [:it | (it at: 1) = $#].
height := (cols at: 1) size.
value := cols collect: [
:it | | first | first := it at: 1.
it count: [:c | c = first]] ]
]
AOC input: [ stdin contents splitDoubleNl collect:
[:it | KeyOrLock new rows: it] ];
part1: [ :input | | locks keys minPos total |
locks := OrderedCollection new.
keys := OrderedCollection new.
input do: [:it | it isLock
ifTrue: [locks add: it value]
ifFalse: [keys add: it value]].
locks := KDTree fromPoints: locks.
total := 0.
minPos := Array new: (keys at: 1) size withAll: 0.
keys do: [
:key | locks from: minPos to: key do: [
:lock |
((key with: lock) allSatisfy: [
:k :l | k >= l ] asSpreader)
ifTrue: [total := total + 1]]].
total ];
result: [ :input :part | part value: input ];
finish.

View file

@ -419,3 +419,77 @@ Random extend [
]. ].
^coll ] ^coll ]
] ]
"--- KDTree ---"
Object subclass: KDTree [
from: min to: max do: block
[ self subclassResponsibility ]
]
KDTree class extend [
fromPoints: points
[ ^self fromShuffledPoints: (Random new shuffle: points asArray) ]
fromShuffledPoints: points
[ ^self fromShuffledPoints: points axis: 1 ]
leafMaxSize [ ^5 ]
fromShuffledPoints: points axis: ax
[ | med splits dims nextAx value |
points size <= self leafMaxSize ifTrue: [^KDLeaf new points: points asArray].
med := self guessMedian: points axis: ax.
dims := med size.
nextAx := ax \\ dims + 1.
value := med at: ax.
splits := self splitPoints: points axis: ax on: value.
^KDInner new
left: (self fromShuffledPoints: (splits at: 1) axis: nextAx)
right: (self fromShuffledPoints: (splits at: 2) axis: nextAx)
axis: ax
value: value ]
splitPoints: points axis: ax on: val
[ | l r fairLeft |
l := OrderedCollection new.
r := OrderedCollection new.
fairLeft := true.
points do: [
:point | | v onLeft |
v := point at: ax.
onLeft := (v < val) or: [
v = val and: [fairLeft := fairLeft not. fairLeft]].
(onLeft ifTrue: [l] ifFalse: [r]) add: point ].
^{l . r} ]
medianGuessSize [ ^5 ]
guessMedian: points axis: ax
[ | arr |
arr := 1 to: (points size min: self medianGuessSize)
collect: [:i | points at: i].
arr sort: [:l :r | (l at: ax) <= (r at: ax)].
^arr at: arr size // 2 + 1 ]
]
KDTree subclass: KDLeaf [
| points |
points: n [points := n. "self class leafSize: points size"]
from: min to: max do: block [ points do: block ]
printOn: st [ st << 'lf' << points ]
]
KDLeaf class extend [
| leafSizes |
leafSizes [ ^leafSizes ifNil: [leafSizes := Bag new] ]
leafSize: sz [ self leafSizes add: sz ]
]
KDTree subclass: KDInner [
| left right axis value |
left: l right: r axis: ax value: v
[left:=l. right:=r. axis:=ax. value:=v]
from: min to: max do: block
[ (min at: axis) <= value ifTrue: [ left from: min to: max do: block ].
(max at: axis) >= value ifTrue: [ right from: min to: max do: block ] ]
printOn: st [ st << '{' << left << ' <= [' << axis << '] '
<< value << ' <= ' << right << '}' ]
]