52 lines
1.6 KiB
Smalltalk
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.
|