diff --git a/.aocrunner.json b/.aocrunner.json index 9dea124..eeaeccf 100644 --- a/.aocrunner.json +++ b/.aocrunner.json @@ -47,16 +47,18 @@ }, { "part1": { - "solved": false, - "result": null, - "attempts": [], - "time": null + "solved": true, + "result": "2358", + "attempts": [ + "0" + ], + "time": 327.70272 }, "part2": { - "solved": false, - "result": null, + "solved": true, + "result": "1737", "attempts": [], - "time": null + "time": 201.22507 } }, { diff --git a/README.md b/README.md index 8e332df..04f02ea 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ [![Day](https://badgen.net/badge/01/%E2%98%85%E2%98%85/green)](src/day01) [![Day](https://badgen.net/badge/02/%E2%98%85%E2%98%85/green)](src/day02) [![Day](https://badgen.net/badge/03/%E2%98%85%E2%98%85/green)](src/day03) -![Day](https://badgen.net/badge/04/%E2%98%86%E2%98%86/gray) +[![Day](https://badgen.net/badge/04/%E2%98%85%E2%98%85/green)](src/day04) ![Day](https://badgen.net/badge/05/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/06/%E2%98%86%E2%98%86/gray) ![Day](https://badgen.net/badge/07/%E2%98%86%E2%98%86/gray) @@ -83,16 +83,16 @@ Both parts: 3.539ms ``` Day 03 -Time part 1: 0.657ms -Time part 2: 0.406ms -Both parts: 1.064ms +Time part 1: 0.811ms +Time part 2: 1.667ms +Both parts: 2.477ms ``` ``` Day 04 -Time part 1: - -Time part 2: - -Both parts: - +Time part 1: 327.703ms +Time part 2: 201.225ms +Both parts: 528.928ms ``` ``` @@ -243,8 +243,8 @@ Both parts: - ``` ``` -Total stars: 6/50 -Total time: 6.946ms +Total stars: 8/50 +Total time: 537.288ms ``` diff --git a/src/day04/README.md b/src/day04/README.md new file mode 100644 index 0000000..dcc7faa --- /dev/null +++ b/src/day04/README.md @@ -0,0 +1,9 @@ +# 🎄 Advent of Code 2024 - day 4 🎄 + +## Info + +Task description: [link](https://adventofcode.com/2024/day/4) + +## Notes + +... \ No newline at end of file diff --git a/src/day04/index.ts b/src/day04/index.ts new file mode 100644 index 0000000..872ca5c --- /dev/null +++ b/src/day04/index.ts @@ -0,0 +1,169 @@ +import run from "aocrunner" + +const parseInput = (rawInput: string) => { + return rawInput.split('\n').map(line => line.split('')) +} + +const directions = ["down","right","dl","dr"] as const +type Direction = typeof directions[number] +type Prospect1 = { + letters: string + direction: Direction + next: [number, number] +} +type Coord = Prospect1['next'] +const getNext = (dir: Direction, [row, col]: Coord): Coord => { + switch(dir) { + case "down": {return [row+1, col]} + case "right": {return [row, col+1]} + case "dl": {return [row+1, col-1]} + case "dr": {return [row+1, col+1]} + } +} + +const part1 = (rawInput: string) => { + const input = parseInput(rawInput) + let total = 0 + let prospects: Prospect1[] = [] + input.forEach((line, row) => { + line.forEach((letter, col) => { + prospects = prospects.map((prospect) => { + const { + direction, + letters, + next + } = prospect + if (next[0] < row) return null + if (next[0] === row && next[1] === col) { + const nextLetters = letters + letter + if (["XMAS","SAMX"].includes(nextLetters)) { + total += 1 + return null + } + if (["XMA","SAM","XM","SA"].includes(nextLetters)) { + return { + letters: nextLetters, + direction: direction, + next: getNext(direction, next) + } + } + } + return prospect + }).filter(prospect => prospect != null) + if ("XMAS".includes(letter)) { + directions.forEach(direction => { + prospects.push({ + letters: letter, + direction, + next: getNext(direction, [row, col]) + }) + }) + } + }) + }) + return total +} + +type Prospect2 = { + letters: string + direction: Direction + next: [number, number] + center: [number, number] +} + +const part2 = (rawInput: string) => { + const input = parseInput(rawInput) + let centers = new Map() + let prospects: Prospect2[] = [] + let total = 0 + input.forEach((line, row) => { + line.forEach((letter, col) => { + prospects = prospects.map((prospect) => { + const { + direction, + letters, + next + } = prospect + if (next[0] < row) return null + if (next[0] === row && next[1] === col) { + const nextLetters = letters + letter + if (["MAS","SAM"].includes(nextLetters)) { + const key = prospect.center.join(",") + if (centers.has(key)) { total++ } + centers.set(key, 1) + return null + } + if (["MA","SA"].includes(nextLetters)) { + return { + ...prospect, + letters: nextLetters, + next: getNext(direction, next), + } + } + } + return prospect + }).filter(prospect => prospect != null) + if ("XMAS".includes(letter)) { + ["dl" as const, "dr" as const].forEach(direction => { + const center = getNext(direction, [row, col]) + prospects.push({ + letters: letter, + direction, + next: center, + center, + }) + }) + } + }) + }) + return total +} + +run({ + part1: { + tests: [ + { + input: `..X... +.SAMX. +.A..A. +XMAS.S +.X....`, + expected: 4 + }, + { + input: `MMMSXXMASM +MSAMXMSMSA +AMXSXMAAMM +MSAMASMSMX +XMASAMXAMM +XXAMMXXAMA +SMSMSASXSS +SAXAMASAAA +MAMMMXMMMM +MXMXAXMASX`, + expected: 18, + }, + ], + solution: part1, + }, + part2: { + tests: [ + { + input: `MMMSXXMASM +MSAMXMSMSA +AMXSXMAAMM +MSAMASMSMX +XMASAMXAMM +XXAMMXXAMA +SMSMSASXSS +SAXAMASAAA +MAMMMXMMMM +MXMXAXMASX`, + expected: 9, + }, + ], + solution: part2, + }, + trimTestInputs: true, + onlyTests: false, +})