Skip to content

Commit

Permalink
Add day 20 of year 2024 πŸ§‘β€πŸŽ„
Browse files Browse the repository at this point in the history
  • Loading branch information
letelete committed Dec 21, 2024
1 parent c15f553 commit bfb0b1f
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 0 deletions.
19 changes: 19 additions & 0 deletions 2024/days/day-20/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Benchmark

```
Platform: darwin arm64
CPU: Apple M3 Pro 11 Cores
Memory: 18.00 GB
```

## Sample 1

| part | time (~) | ΞΌs |
| ---- | -------- | ------------------ |
| 1 | 4.48ms | 4.4783750000000015 |

## Answer

| part | time (~) | ΞΌs |
| ---- | -------- | ------------ |
| 1 | 11.930s | 11929.655666 |
15 changes: 15 additions & 0 deletions 2024/days/day-20/in.sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
###############
#...#...#.....#
#.#.#.#.#.###.#
#S#...#.#.#...#
#######.#.#.###
#######.#.#...#
#######.#.###.#
###..E#...#...#
###.#######.###
#...###...#...#
#.#####.#.###.#
#.#...#.#.#...#
#.#.#.#.#.#.###
#...#...#...###
###############
121 changes: 121 additions & 0 deletions 2024/days/day-20/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
function parse(source) {
return source
.trim()
.split('\n')
.map((e) => e.split(''));
}

function findTile(grid, char) {
const row = grid.findIndex((row) => row.includes(char));
return [row, grid[row].indexOf(char)];
}

const symbols = { start: 'S', end: 'E', wall: '#', track: '.' };
const dirs = {
orthogonal: [
[0, -1],
[-1, 0],
[0, 1],
[1, 0],
],
};

function inRange(data, row, col) {
return row >= 0 && row < data.length && col >= 0 && col < data[0].length;
}

const hash = (row, col) => `${row},${col}`;

function bfs(grid, start, end, visited, trackPath, memo = new Map()) {
const startKey = `${hash(...start)}->${hash(...end)}`;
if (memo.has(startKey)) return memo.get(startKey);

const q = [[0, start]],
source = new Map();

while (q.length) {
const [steps, [row, col]] = q.shift();
const key = hash(row, col);
if (visited.has(key)) continue;
visited.add(key);

if (row === end[0] && col === end[1]) {
if (!trackPath) {
memo.set(startKey, steps);
return steps;
}
const path = [[row, col]];
let head = source.get(key);
while (head) {
path.push(head.split(',').map(Number));
head = source.get(head);
}
const result = [steps, path.reverse()];
memo.set(startKey, result);
return result;
}

dirs.orthogonal.forEach(([drow, dcol]) => {
const [nextRow, nextCol] = [row + drow, col + dcol];
if (
inRange(grid, nextRow, nextCol) &&
grid[nextRow][nextCol] !== symbols.wall &&
!visited.has(hash(nextRow, nextCol))
) {
q.push([steps + 1, [nextRow, nextCol]]);
source.set(hash(nextRow, nextCol), key);
}
});
}
memo.set(startKey, -1);
return -1;
}

function part1(data) {
const end = findTile(data, symbols.end),
start = findTile(data, symbols.start);
const memo = new Map();
const [minSteps, path] = bfs(data, start, end, new Set(), true, memo);

const visited = new Set(),
saves = new Map();
path.forEach(([row, col], steps) => {
visited.add(hash(row, col));
dirs.orthogonal.forEach(([drow, dcol]) => {
const [nextRow, nextCol] = [row + drow, col + dcol];
const nextKey = hash(nextRow, nextCol);
if (
inRange(data, nextRow, nextCol) &&
data[nextRow][nextCol] === symbols.wall &&
!visited.has(nextKey)
) {
const bfsres = bfs(
data,
[nextRow, nextCol],
end,
new Set(visited),
false,
memo
);
if (bfsres !== -1) {
const candidate = steps + bfsres + 1;
if (candidate < minSteps)
saves.set(candidate, (saves.get(candidate) ?? 0) + 1);
}
}
});
});

return [
minSteps,
[...saves.entries()]
.filter(([k]) => minSteps - k >= 100)
.reduce((sum, [_, v]) => sum + v, 0),
];
}

function part2() {
return null;
}

module.exports = { parse, part1, part2 };

0 comments on commit bfb0b1f

Please sign in to comment.