diff --git a/days/day13.st b/days/day13.st new file mode 100644 index 0000000..2ed0d22 --- /dev/null +++ b/days/day13.st @@ -0,0 +1,57 @@ +Object subclass: Machine [ + | vecA vecB prize | + parse: line + [ line scanf: 'Button A: X+%d, Y+%d Button B: X+%d, Y+%d Prize: X=%d, Y=%d' + with: [ :aX :aY :bX :bY :pX :pY | + vecA := Posn x: aX y: aY. + vecB := Posn x: bX y: bY. + prize := Posn x: pX y: pY ] ] + + printOn: st + [ st << '{A: ' << vecA << '; B: ' << vecB << '; P: ' << prize << '}' ] + + priceA [^3] priceB [^1] + + solve: offV + [ ^(Mat2 col: vecA col: vecB) inverse + ifNotNil: [ + :inv | | vec | + vec := inv *> (prize + offV). + (vec x isInteger and: [vec y isInteger]) + ifTrue: [^vec] + ifFalse: [^nil] ] + ifNil: [ + "linearly dependent -- not actually reached" + | slvA slvB | + 'Linearly dependent!' displayNl. + slvA := self solveLinDep: vecA. + slvB := self solveLinDep: vecB. + slvA ifNil: [ + slvB ifNil: [^nil] + ifNotNil: [^Posn x: 0 y: slvB]]. + slvB ifNil: [^Posn x: slvA y: 0]. + ((slvA * self priceA) <= (slvB * self priceB)) + ifTrue: [^Posn x: slvA y: 0] + ifFalse: [^Posn x: 0 y: slvB]] ] + + tokenCost: soln + [ soln ifNil: [^0]. + ^(soln x * self priceA) + (soln y * self priceB) ] + + solveCost: offV [ ^self tokenCost: (self solve: offV) ] + + solveLinDep: vec + [ | sf | + sf := prize x / vec x. + (prize y / vec y) = sf ifFalse: [^nil]. + sf isInteger ifFalse: [^nil]. + ^sf ] +] + +AOC input: [ stdin chain contents; tokenize: (String with: $<10> with: $<10>); + collect: [:it | Machine new parse: it] ]; + part1: 0; part2: 10000000000000; + result: [ :machines :off | | offV | + offV := Posn x: off y: off. + machines inject: 0 into: [:a :it | a + (it solveCost: offV)] ]; + finish. diff --git a/days/utils.st b/days/utils.st index 198e273..0e81104 100644 --- a/days/utils.st +++ b/days/utils.st @@ -236,6 +236,38 @@ Posn class extend [ zero [^Posn x: 0 y: 0] ] +Object subclass: Mat2 [ + | m11 m12 + m21 m22 | + m11: n11 m12: n12 m21: n21 m22: n22 [m11:=n11. m12:=n12. m21:=n21. m22:=n22] + + determinant [ ^(m11 * m22) - (m12 * m21) ] + inverse + [ | det r rn | det := self determinant. + det = det zero ifTrue: [^nil]. + r := det reciprocal. + rn := r negated. + ^Mat2 m11: r * m22 m12: rn * m12 + m21: rn * m21 m22: r * m11 ] + + *> p [ ^Posn x: (m11 * p x) + (m12 * p y) + y: (m21 * p x) + (m22 * p y) ] + + printOn: st [ st << ('{ %1, %2 ; %3, %4 }' % {m11. m12. m21. m22}) ] +] +Mat2 class extend [ + m11: n11 m12: n12 m21: n21 m22: n22 + [ ^self new m11: n11 m12: n12 m21: n21 m22: n22 ] + + col: a col: b + [ ^self m11: a x m12: b x + m21: a y m22: b y ] + + row: a row: b + [ ^self m11: a x m12: a y + m21: b x m22: b y ] +] + Array extend [ asPosn [ ^Posn x: (self at: 1) y: (self at: 2) ] ] Iterable extend [ asPosns [ ^self collect: [:it | it asPosn] ] ]