aoc2024/days/day07.st
2024-12-07 11:38:55 +00:00

52 lines
1.6 KiB
Smalltalk

Object subclass: AddOp
[ tryDo: n target: tgt [ ^tgt - n ] ]
Object subclass: MulOp
[ tryDo: n target: tgt
[ (tgt rem: n) = 0 ifFalse: [^nil].
^tgt quo: n ] ]
MulOp subclass: CatOp
[ tryDo: n target: tgt
[ | p10 |
p10 := (n + 1) ceilingLog: 10.
p10 := 10 raisedTo: p10.
^super tryDo: p10 target: tgt - n ] ]
Object subclass: Equation [
| target numbers |
target: n [target:=n] numbers: n [numbers:=n]
testValue [^target]
printOn: dst [dst << target << ': ' << numbers]
"Backtracking search right-to-left over the number sequence."
canSolveFrom: idx target: tgt with: ops
[ | n n1 ok | n := numbers at: idx.
idx = 1 ifTrue: [^n = tgt].
tgt < n ifTrue: [^false].
ops do: [
:op | n1 := op tryDo: n target: tgt.
n1 ifNotNil: [
ok := self canSolveFrom: idx - 1 target: n1 with: ops.
ok ifTrue: [^true] ]].
^false ]
canSolveWith: ops [^self canSolveFrom: numbers size target: target with: ops]
]
Equation class extend [
parse: line
[^(line tokenize: ': ') letArrayInBlock: [
:target :numbers |
Equation new target: target asNumber;
numbers: ((numbers tokenize: ' ')
collect: [:it|it asNumber])]]
]
AOC input: [ stdin toLines collect: [:line | Equation parse: line] ];
part1: {MulOp new. AddOp new};
part2: {CatOp new. MulOp new. AddOp new};
result: [ :eqns :part |
eqns chain select: [:eqn | eqn canSolveWith: part];
collect: [:it | it testValue];
sum ];
finish.