diff --git a/.aocrunner.json b/.aocrunner.json index ef07057..1b653e8 100644 --- a/.aocrunner.json +++ b/.aocrunner.json @@ -299,16 +299,16 @@ }, { "part1": { - "solved": false, - "result": null, + "solved": true, + "result": "1002474", "attempts": [], - "time": null + "time": 0.08 }, "part2": { - "solved": false, - "result": null, + "solved": true, + "result": "919758187195363", "attempts": [], - "time": null + "time": 147.4 } }, { diff --git a/README.md b/README.md index 4392cd4..f062370 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ [![Day](https://badgen.net/badge/18/%E2%98%85%E2%98%85/green)](src/day18) ![Day](https://badgen.net/badge/19/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/20/%E2%98%86%E2%98%86/gray) -![Day](https://badgen.net/badge/21/%E2%98%86%E2%98%86/gray) +[![Day](https://badgen.net/badge/21/%E2%98%85%E2%98%85/green)](src/day21) ![Day](https://badgen.net/badge/22/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/23/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/24/%E2%98%86%E2%98%86/gray) @@ -188,9 +188,9 @@ Both parts: 430.38ms ``` Day 18 -Time part 1: 38.77ms -Time part 2: 147.3ms -Both parts: 186.07000000000002ms +Time part 1: 35.41ms +Time part 2: 268.36ms +Both parts: 303.77ms ``` ``` @@ -209,9 +209,9 @@ Both parts: - ``` Day 21 -Time part 1: - -Time part 2: - -Both parts: - +Time part 1: 0.08ms +Time part 2: 147.4ms +Both parts: 147.48000000000002ms ``` ``` @@ -243,8 +243,8 @@ Both parts: - ``` ``` -Total stars: 36/50 -Total time: 2519.45ms +Total stars: 38/50 +Total time: 2784.6299999999997ms ``` diff --git a/src/day21/README.md b/src/day21/README.md new file mode 100644 index 0000000..09f4be1 --- /dev/null +++ b/src/day21/README.md @@ -0,0 +1,9 @@ +# 🎄 Advent of Code 2021 - day 21 🎄 + +## Info + +Task description: [link](https://adventofcode.com/2021/day/21) + +## Notes + +... \ No newline at end of file diff --git a/src/day21/index.js b/src/day21/index.js new file mode 100644 index 0000000..803a6a2 --- /dev/null +++ b/src/day21/index.js @@ -0,0 +1,85 @@ +import run from "aocrunner" + +const parseInput = (rawInput) => rawInput.match(/(?<=: )\d+/g).map(x=>+x) + +const part1 = (rawInput) => { + const [aStart, bStart] = parseInput(rawInput) + let a = aStart, b = bStart, aScore = 0, bScore = 0, isATurn = true + let die = 0, numRolls = 0 + function roll() { + numRolls++ + return (die = die % 100 + 1) + } + while (aScore < 1000 && bScore < 1000) { + const rolls = [roll(),roll(),roll()] + if (isATurn) { + a += rolls[0] + rolls[1] + rolls[2] + a = (a - 1) % 10 + 1 + aScore += a + } else { + b += rolls[0] + rolls[1] + rolls[2] + b = (b - 1) % 10 + 1 + bScore += b + } + isATurn = !isATurn + } + return Math.min(aScore, bScore) * numRolls +} + +const frequencies = [] +for (let i = 1; i <= 3; i++) + for (let j = 1; j <= 3; j++) + for (let k = 1; k <= 3; k++) { + frequencies[i + j + k] = (frequencies[i + j + k] ?? 0) + 1 + } + +const part2 = (rawInput) => { + const [aStart, bStart] = parseInput(rawInput) + const memo = [] + const winThreshold = 21 + function countWins(aScore, bScore, aPos, bPos, isATurn) { + let existing = memo[[aScore, bScore, aPos, bPos, isATurn]] + if (existing !== undefined) return existing + if (aScore >= winThreshold) { + memo[[aScore, bScore, aPos, bPos, isATurn]] = [1, 0] + return [1, 0] + } + if (bScore >= winThreshold) { + memo[[aScore, bScore, aPos, bPos, isATurn]] = [0, 1] + return [0, 1] + } + let totalWins = [0, 0] + for (let diceSum = 3; diceSum <= 9; diceSum++) { + let thisWin + if (isATurn) { + const nextAPos = (aPos - 1 + diceSum) % 10 + 1 + thisWin = countWins(aScore + nextAPos, bScore, nextAPos, bPos, !isATurn) + } else { + const nextBPos = (bPos - 1 + diceSum) % 10 + 1 + thisWin = countWins(aScore, bScore + nextBPos, aPos, nextBPos, !isATurn) + } + totalWins = [totalWins[0] + frequencies[diceSum] * thisWin[0], totalWins[1] + frequencies[diceSum] * thisWin[1]] + } + memo[[aScore, bScore, aPos, bPos, isATurn]] = totalWins + return totalWins + } + return Math.max(...countWins(0, 0, aStart, bStart, true)) +} + +run({ + part1: { + tests: [ + { input: `Player 1 starting position: 4 +Player 2 starting position: 8`, expected: 739785 }, + ], + solution: part1, + }, + part2: { + tests: [ + { input: `Player 1 starting position: 4 +Player 2 starting position: 8`, expected: 444356092776315 }, + ], + solution: part2, + }, + trimTestInputs: true, +})