diff --git a/days/15/main.ts b/days/15/main.ts new file mode 100644 index 0000000..240f558 --- /dev/null +++ b/days/15/main.ts @@ -0,0 +1,103 @@ +import { loadInput } from "utils"; + +export function part1(input: Array) { + const { walls, boxes, initialRobotPosition, moves, width, height } = + parseInput(input); + let robotPosition = initialRobotPosition; + // console.log("Initial state:"); + for (const move of moves) { + // print(robotPosition, walls, boxes, width, height); + // console.log(`Move ${move}:`); + const directionVector = + directionVectors[move as unknown as keyof typeof directionVectors]!; + const potentialNewRobotPosition = robotPosition + directionVector; + if (walls.has(potentialNewRobotPosition)) continue; + if (!boxes.has(potentialNewRobotPosition)) { + robotPosition = potentialNewRobotPosition; + continue; + } + for ( + let next = potentialNewRobotPosition + directionVector; + !walls.has(next); + next += directionVector + ) { + if (boxes.has(next)) { + continue; + } + boxes.delete(potentialNewRobotPosition); + boxes.add(next); + robotPosition = potentialNewRobotPosition; + break; + } + } + // print(robotPosition, walls, boxes, width, height); + return boxes.values().reduce((acc, gps) => acc + gps, 0); +} + +export function part2(input: Array) { + return 0; +} + +function parseInput(input: Array) { + const walls = new Set(); + const boxes = new Set(); + let initialRobotPosition = -1; + const delimiterIndex = input.indexOf(""); + const moves = input.slice(delimiterIndex + 1).join(""); + const map = input.slice(0, delimiterIndex); + for (let y = 0; y < map.length; y++) { + const row = map[y]; + for (let x = 0; x < row.length; x++) { + const char = row[x]; + if (char === ".") continue; + else if (char === "#") walls.add(gpsCoordinate(x, y)); + else if (char === "O") boxes.add(gpsCoordinate(x, y)); + else if (char === "@") initialRobotPosition = gpsCoordinate(x, y); + } + } + return { + walls, + boxes, + initialRobotPosition, + moves, + width: map.length, + height: map[0].length, + }; +} + +const directionVectors = { + "^": gpsCoordinate(0, -1), + ">": gpsCoordinate(1, 0), + "v": gpsCoordinate(0, 1), + "<": gpsCoordinate(-1, 0), +}; + +function gpsCoordinate(x: number, y: number) { + return 100 * y + x; +} + +function print( + robot: number, + walls: Set, + boxes: Set, + width: number, + height: number, +) { + for (let y = 0; y < height; y++) { + let row = ""; + for (let x = 0; x < width; x++) { + const gps = gpsCoordinate(x, y); + if (walls.has(gps)) row += "#"; + else if (boxes.has(gps)) row += "O"; + else if (robot === gps) row += "@"; + else row += "."; + } + console.log(row); + } + console.log(""); +} + +if (import.meta.main) { + console.log(part1(await loadInput(15))); + console.log(part2(await loadInput(15))); +} diff --git a/days/15/main_test.ts b/days/15/main_test.ts new file mode 100644 index 0000000..0ae8c74 --- /dev/null +++ b/days/15/main_test.ts @@ -0,0 +1,61 @@ +import { expect } from "@std/expect"; +import { describe, it } from "@std/testing/bdd"; +import { part1, part2 } from "./main.ts"; +import { loadInput } from "utils"; + +describe("day 15 example", () => { + it("part 1 small", () => { + expect(part1([ + "########", + "#..O.O.#", + "##@.O..#", + "#...O..#", + "#.#.O..#", + "#...O..#", + "#......#", + "########", + "", + "<^^>>>vv>v<<", + ])).toBe(2028); + }); + + it("part 1 large", () => { + expect(part1([ + "##########", + "#..O..O.O#", + "#......O.#", + "#.OO..O.O#", + "#..O@..O.#", + "#O#..O...#", + "#O..O..O.#", + "#.OO.O.OO#", + "#....O...#", + "##########", + "", + "^v>^vv^v>v<>v^v<<><>>v^v^>^<<<><^", + "vvv<<^>^v^^><<>>><>^<<><^vv^^<>vvv<>><^^v>^>vv<>v<<<^<^^>>>^<>vv>v^v^<>><>>>><^^>vv>v<^^^>>v^v^<^^>v^^>v^<^v>v<>>v^v^v^^<^^vv<", + "<>^^^^>>>v^<>vvv^>^^^vv^^>v<^^^^v<>^>vvvv><>>v^<<^^^^^", + "^><^><>>><>^^<<^^v>>><^^>v>>>^v><>^v><<<>vvvv>^<><<>^><", + "^>><>^v<><^vvv<^^<><^v<<<><<<^^<^>>^<<<^>>^v^>>^v>vv>^<<^v<>><<><<>v<^vv<<<>^^v^>^^>>><<^v>>v^v><^^>>^<>vv^", + "<><^^>^^^<>^vv<<^><<><<><<<^^<<<^<<>><<><^^^>^^<>^>v<>", + "^^>vv<^v^v^<>^^^>>>^^vvv^>vvv<>>>^<^>>>>>^<<^v>^vvv<>^<><", + "v^^>>><<^^<>>^v^v^<<>^<^v^v><^<<<><<^vv>>v>v^<<^", + ])).toBe(10092); + }); + + it.ignore("part 2", () => { + expect(part2([])).toBe(-1); + }); +}); + +describe("day 15 solution", () => { + it("part 1", async () => { + expect(part1(await loadInput(15))).toBe(1441031); + }); + + it.ignore("part 2", async () => { + expect(part2(await loadInput(15))).toBe(-1); + }); +}); diff --git a/days/mod.ts b/days/mod.ts index 35da622..c775149 100644 --- a/days/mod.ts +++ b/days/mod.ts @@ -3,7 +3,7 @@ type Solution = { part1: PartFunction; part2: PartFunction }; const days = new Map(); -for (const day of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14]) { +for (const day of [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15]) { days.set(day, await import(`./${day}/main.ts`)); }