Skip to content

Commit

Permalink
down to 20 secs
Browse files Browse the repository at this point in the history
  • Loading branch information
shahata committed Dec 23, 2023
1 parent fc6454c commit b60830d
Showing 1 changed file with 27 additions and 37 deletions.
64 changes: 27 additions & 37 deletions src/2023/day23.js
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
function addTeleports(map) {
function findTeleports(map) {
const teleports = {};
for (let y = 0; y < map.length; y++) {
for (let x = 0; x < map.length; x++) {
for (let x = 0; x < map[0].length; x++) {
if (map[y][x] === '#') continue;
const neighbors = getNeighbors(map, { x, y }, []);
const neighbors = getNeighbors(map, { x, y });
if (neighbors.length === 2) continue;
neighbors.forEach(n => {
let neighbors;
let curr = n;
let prev = { x, y };
const trail = [prev];
while (n) {
const neighbors = getNeighbors(map, n, [`${prev.x},${prev.y}`]);
trail.push(n);
prev = n;
if (neighbors.length === 1) n = neighbors[0];
else n = null;
}
if (trail.length > 2) {
const key1 = `${trail.at(1).x},${trail.at(1).y}`;
const key2 = `${trail.at(-2).x},${trail.at(-2).y}`;
teleports[key1] = { dest: trail.at(-1), steps: trail.length - 2 };
teleports[key2] = { dest: trail.at(0), steps: trail.length - 2 };
}
let steps = -1;
do {
neighbors = getNeighbors(map, curr, [`${prev.x},${prev.y}`]);
steps++;
prev = curr;
curr = neighbors[0];
} while (neighbors.length === 1);
if (steps > 0) teleports[`${n.x},${n.y}`] = { dest: prev, steps };
});
}
}
return teleports;
}

function getNeighbors(map, { x, y }, visited) {
function getNeighbors(map, { x, y, steps = 0 }, visited = [], teleports = {}) {
let neighbors = [
{ x: x + 1, y },
{ x: x - 1, y },
{ x, y: y + 1 },
{ x, y: y - 1 },
{ x: x + 1, y, steps: steps + 1 },
{ x: x - 1, y, steps: steps + 1 },
{ x, y: y + 1, steps: steps + 1 },
{ x, y: y - 1, steps: steps + 1 },
];
if (map[y][x] === '>') neighbors = [neighbors[0]];
if (map[y][x] === '<') neighbors = [neighbors[1]];
if (map[y][x] === 'v') neighbors = [neighbors[2]];
if (map[y][x] === '^') neighbors = [neighbors[3]];
neighbors = neighbors.map(n => {
const { dest, steps } = teleports[`${n.x},${n.y}`] || {};
return dest ? { ...dest, steps: n.steps + steps } : n;
});
return neighbors.filter(
n =>
map[n.y]?.[n.x] &&
Expand All @@ -52,27 +52,17 @@ function solve(map, teleports, start, end) {
const stack = [start];
while (stack.length > 0) {
const next = stack.pop();
while (path.length > next.len) path.pop();
path.push(`${next.x},${next.y}`);
if (next.x === end.x && next.y === end.y) {
best = Math.max(best, next.steps);
} else if (teleports[`${next.x},${next.y}`]) {
const { dest, steps } = teleports[`${next.x},${next.y}`];
if (!path.includes(`${dest.x},${dest.y}`)) {
stack.push({ ...dest, steps: next.steps + steps, len: path.length });
}
} else {
getNeighbors(map, next, path).forEach(n =>
stack.push({ ...n, steps: next.steps + 1, len: path.length }),
);
}
path.splice(next.len, Infinity, `${next.x},${next.y}`);
if (next.x === end.x && next.y === end.y) best = Math.max(best, next.steps);
const neighbors = getNeighbors(map, next, path, teleports);
neighbors.forEach(n => stack.push({ ...n, len: path.length }));
}
return best;
}

export function part1(input) {
const map = input.split('\n').map(line => line.split(''));
const teleports = addTeleports(map);
const teleports = findTeleports(map);
let start = { x: 1, y: 0, steps: 0, len: 0 };
let end = { x: map.length - 2, y: map.length - 1 };
return solve(map, teleports, start, end);
Expand Down

0 comments on commit b60830d

Please sign in to comment.