diff --git a/days/day22.st b/days/day22.st index 0500a30..2c1a90f 100644 --- a/days/day22.st +++ b/days/day22.st @@ -3,24 +3,48 @@ Object subclass: Monkey [ history: h [history := h] lastValue [^history at: history size] - collectPricesInto: intoTbl - [ | ch table prices deltas chMod | - table := Dictionary new. + collectPricesInto: intoTbl seen: seenTbl + [ | ch prices deltas key newV prevSeen localBest | prices := history collect: [:it | it \\ 10]. deltas := 2 to: history size collect: [ - :i | (prices at: i) - (prices at: i - 1) + 9]. - ch := 0. - 1 to: 4 do: [ - :i | ch := 20 * ch + (deltas at: i)]. - chMod := 20 raisedTo: 4. + :i | (prices at: i) - (prices at: i - 1) + 9]. + ch := 0. "past four deltas as a base-19 integer" + 1 to: 4 do: [:i | ch := 19 * ch + (deltas at: i)]. + "Accumulate the best value globally, (local variable as a + 'compiler' optimisation)." + localBest := Monkey bestBananas. 5 to: deltas size do: [ - :i | ch := (20 * ch + (deltas at: i)) \\ chMod. - table at: ch ifAbsentPut: [prices at: i + 1]]. - table keysAndValuesDo: [ - :ch :v | intoTbl at: ch put: v + (intoTbl at: ch ifAbsent: [0])]] + :i | ch := (19 * ch + (deltas at: i)) \\ 130321. + "ch is theoretically in the range [0,19^4), + so add 1 to keep it in array range" + key := ch + 1. + (seenTbl at: key) == false ifTrue: [ + "Store a linked list of seen values within the table, + to make resetting it easier." + seenTbl at: key put: prevSeen. + prevSeen := key. + newV := (prices at: i + 1) + (intoTbl at: key). + intoTbl at: key put: newV. + newV > localBest ifTrue: [localBest := newV]. + ]]. + Monkey bestBananas: localBest. + "Reset the seen table via the linked list." + [prevSeen notNil] whileTrue: [ + | tmp | tmp := seenTbl at: prevSeen. + seenTbl at: prevSeen put: false. + prevSeen := tmp. ]] ] Monkey class extend [ + | bestV | + bestBananas: v [bestV := v] + bestBananas [^bestV] + + initialize [bestV := 0] + + keyDigits [^19] + keyMax [^130321 "19 raisedTo: 4"] + stepSecret: initial times: n [ | s hist | s := initial. hist := 1 to: n collect: [ @@ -31,12 +55,15 @@ Monkey class extend [ s ]. ^Monkey new history: {initial},hist ] ] +Monkey initialize. AOC input: [ stdin toLines collect: [ :it | Monkey stepSecret: it asNumber times: 2000] ]; part1: [ :monkeys | (monkeys collect: [:it | it lastValue]) sum ]; - part2: [ :monkeys | | buyMap | buyMap := Dictionary new. - monkeys do: [:it | it collectPricesInto: buyMap]. - buyMap values maximum ]; + part2: [ :monkeys | | buyMap seenMap | + buyMap := Array new: Monkey keyMax withAll: 0. + seenMap := Array new: Monkey keyMax withAll: false. + monkeys do: [:it | it collectPricesInto: buyMap seen: seenMap]. + Monkey bestBananas ]; result: [ :monkeys :part | part value: monkeys ]; finish.