Day 18
This commit is contained in:
166
2024/18/index.ts
166
2024/18/index.ts
@@ -14,9 +14,7 @@ enum Dir {
|
|||||||
Left,
|
Left,
|
||||||
};
|
};
|
||||||
|
|
||||||
const map: Array<Array<string>> = [];
|
const map: Array<Array<string|number>> = [];
|
||||||
|
|
||||||
const path: Array<Coord> = [];
|
|
||||||
|
|
||||||
const width = 71;
|
const width = 71;
|
||||||
const height = 71;
|
const height = 71;
|
||||||
@@ -35,14 +33,14 @@ for (let i = 0; i < 1024; i++) {
|
|||||||
map[y][x] = '#'
|
map[y][x] = '#'
|
||||||
}
|
}
|
||||||
|
|
||||||
function get(pos: Coord): string {
|
function get(pos: Coord): string|number {
|
||||||
if (map[pos.y] && map[pos.y][pos.x]) {
|
if (map[pos.y] && map[pos.y][pos.x]) {
|
||||||
return map[pos.y][pos.x];
|
return map[pos.y][pos.x];
|
||||||
}
|
}
|
||||||
return '#';
|
return '#';
|
||||||
}
|
}
|
||||||
|
|
||||||
function set(pos: Coord, val: string): void {
|
function set(pos: Coord, val: string|number): void {
|
||||||
map[pos.y][pos.x] = val;
|
map[pos.y][pos.x] = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,26 +58,12 @@ function prevDir(dir: Dir): Dir {
|
|||||||
return directions[i];
|
return directions[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
function isBranch(pos: Coord, dir: Dir): boolean {
|
|
||||||
const leftDir = prevDir(dir);
|
|
||||||
const rightDir = nextDir(dir);
|
|
||||||
const next = nextCoord(pos, dir);
|
|
||||||
const left = nextCoord(pos, leftDir);
|
|
||||||
const right = nextCoord(pos, rightDir);
|
|
||||||
const nextChar = get(next);
|
|
||||||
const leftChar = get(left);
|
|
||||||
const rightChar = get(right);
|
|
||||||
return nextChar === '.' && leftChar === '.'
|
|
||||||
|| nextChar === '.' && rightChar === '.'
|
|
||||||
|| leftChar === '.' && rightChar === '.';
|
|
||||||
}
|
|
||||||
|
|
||||||
function printMap(path: Array<Coord> = []) {
|
function printMap(path: Array<Coord> = []) {
|
||||||
const mapClone = map.slice().map((row: Array<string>) => row.slice());
|
const mapClone = map.slice().map((row: Array<string|number>) => row.slice());
|
||||||
path.forEach(({ x, y }) => {
|
path.forEach(({ x, y }) => {
|
||||||
mapClone[y][x] = 'O';
|
mapClone[y][x] = 'O';
|
||||||
});
|
});
|
||||||
console.log(mapClone.map((row: Array<string>) => row.join('')).join("\n"));
|
console.log(mapClone.map((row: Array<string|number>) => row.map((c) => typeof c === 'number' ? '.' : c).join('')).join("\n"));
|
||||||
console.log("\n");
|
console.log("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,105 +98,53 @@ function fillDeadEnd(pos: Coord): void {
|
|||||||
}
|
}
|
||||||
printMap();
|
printMap();
|
||||||
|
|
||||||
// for (let y = 0; y < height; y++) {
|
for (let y = 0; y < height; y++) {
|
||||||
// for (let x = 0; x < width; x++) {
|
for (let x = 0; x < width; x++) {
|
||||||
// const pos = { x, y };
|
const pos = { x, y };
|
||||||
// const char = get(pos);
|
const char = get(pos);
|
||||||
// if (char !== '.') {
|
if (char !== '.') {
|
||||||
// continue;
|
continue;
|
||||||
// }
|
|
||||||
// if (isDeadEnd(pos)) {
|
|
||||||
// fillDeadEnd(pos);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// printMap();
|
|
||||||
|
|
||||||
interface Nd {
|
|
||||||
parent: Nd|null,
|
|
||||||
pos: Coord,
|
|
||||||
g: number,
|
|
||||||
h: number,
|
|
||||||
f: number,
|
|
||||||
};
|
|
||||||
|
|
||||||
const openList: Array<Nd> = [];
|
|
||||||
const closedList: Array<Nd> = [];
|
|
||||||
|
|
||||||
const startNode: Nd = {
|
|
||||||
parent: null,
|
|
||||||
pos: { x: 0, y: 0 },
|
|
||||||
g: 0,
|
|
||||||
h: 0,
|
|
||||||
f: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
const endNode = {
|
|
||||||
parent: null,
|
|
||||||
pos: { x: width - 1, y: height - 1 },
|
|
||||||
g: 0,
|
|
||||||
h: 0,
|
|
||||||
f: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
openList.push(startNode);
|
|
||||||
|
|
||||||
while (openList.length > 0) {
|
|
||||||
let currentNode = openList[0];
|
|
||||||
let currentIndex = 0;
|
|
||||||
openList.forEach((item, index) => {
|
|
||||||
if (item.f < currentNode.f) {
|
|
||||||
currentNode = item;
|
|
||||||
currentIndex = index;
|
|
||||||
}
|
}
|
||||||
});
|
if (isDeadEnd(pos)) {
|
||||||
|
fillDeadEnd(pos);
|
||||||
openList.splice(currentIndex, 1);
|
|
||||||
closedList.push(currentNode);
|
|
||||||
|
|
||||||
if (currentNode.pos.x === endNode.pos.x && currentNode.pos.y === endNode.pos.y) {
|
|
||||||
let current: Nd|null = currentNode;
|
|
||||||
while (current) {
|
|
||||||
path.push(current.pos);
|
|
||||||
current = current.parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const children: Array<Nd> = [];
|
|
||||||
|
|
||||||
[Dir.Up, Dir.Right, Dir.Down, Dir.Left].forEach((dir) => {
|
|
||||||
const nodePos = nextCoord(currentNode.pos, dir);
|
|
||||||
|
|
||||||
if (get(nodePos) === '#') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const newNode: Nd = {
|
|
||||||
parent: currentNode,
|
|
||||||
pos: nodePos,
|
|
||||||
g: 0,
|
|
||||||
h: 0,
|
|
||||||
f: 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (closedList.find((closedChild) => closedChild.pos.x === newNode.pos.x && closedChild.pos.y === newNode.pos.y)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
newNode.g = currentNode.g + 1;
|
|
||||||
newNode.h = ((newNode.pos.x - endNode.pos.x) ** 2) + ((newNode.pos.y - endNode.pos.y) ** 2);
|
|
||||||
newNode.f = newNode.g + newNode.h;
|
|
||||||
|
|
||||||
if (openList.find((openNode) => newNode.pos.x === openNode.pos.x && newNode.pos.y === openNode.pos.y && newNode.g > openNode.g)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
openList.push(newNode);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
printMap();
|
printMap();
|
||||||
console.log(path, path.length)
|
|
||||||
|
let fastest: number|null = null;
|
||||||
|
|
||||||
|
const scores: Array<Array<Coord>> = [];
|
||||||
|
|
||||||
|
function getScoresAfterPosition(pos: Coord, dir: Dir, path: Array<Coord> = [], lastBranch: [number, Coord]|null = null): void {
|
||||||
|
if (fastest !== null && path.length >= fastest) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[dir, nextDir(dir), prevDir(dir)].forEach((newDir, i) => {
|
||||||
|
const next = nextCoord(pos, newDir);
|
||||||
|
const nextCell = get(next);
|
||||||
|
if (nextCell !== '#' && (typeof nextCell !== 'number' || nextCell > path.length) && !path.find(({ x, y }) => next.x === x && next.y === y)) {
|
||||||
|
if (next.x === width - 1 && next.y === height - 1) {
|
||||||
|
if (fastest === null || path.length < fastest) {
|
||||||
|
fastest = path.length;
|
||||||
|
}
|
||||||
|
scores.push(path);
|
||||||
|
return;
|
||||||
|
} else if (next.x >= 0 && next.x < width && next.y >= 0 && next.y < height) {
|
||||||
|
set(next, path.length);
|
||||||
|
getScoresAfterPosition(next, newDir, [...path, next], lastBranch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getScoresAfterPosition({ x: 0, y: 0 }, Dir.Up, [{ x: 0, y: 0 }]);
|
||||||
|
|
||||||
|
console.log(scores);
|
||||||
|
const fastestScore = Math.min(...scores.map((p) => p.length));
|
||||||
|
const fastestPath = scores.find((p) => p.length === fastestScore);
|
||||||
|
printMap(fastestPath);
|
||||||
|
console.log(fastestScore);
|
||||||
|
|||||||
163
2024/18/index2.ts
Normal file
163
2024/18/index2.ts
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8').split("\n");
|
||||||
|
|
||||||
|
interface Coord {
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Dir {
|
||||||
|
Up,
|
||||||
|
Right,
|
||||||
|
Down,
|
||||||
|
Left,
|
||||||
|
};
|
||||||
|
|
||||||
|
const map: Array<Array<string|number>> = [];
|
||||||
|
|
||||||
|
const width = 71;
|
||||||
|
const height = 71;
|
||||||
|
|
||||||
|
for (let y = 0; y < height; y++) {
|
||||||
|
if (!map[y]) {
|
||||||
|
map[y] = [];
|
||||||
|
}
|
||||||
|
for (let x = 0; x < width; x++) {
|
||||||
|
map[y][x] = '.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < 1024; i++) {
|
||||||
|
const [x, y] = input[i].split(',').map((st: string) => parseInt(st));
|
||||||
|
map[y][x] = '#'
|
||||||
|
}
|
||||||
|
|
||||||
|
function get(pos: Coord): string|number {
|
||||||
|
if (map[pos.y] && map[pos.y][pos.x]) {
|
||||||
|
return map[pos.y][pos.x];
|
||||||
|
}
|
||||||
|
return '#';
|
||||||
|
}
|
||||||
|
|
||||||
|
function set(pos: Coord, val: string|number): void {
|
||||||
|
map[pos.y][pos.x] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextDir(dir: Dir): Dir {
|
||||||
|
const directions = [Dir.Up, Dir.Right, Dir.Down, Dir.Left];
|
||||||
|
const i = (directions.indexOf(dir) + 1) % directions.length;
|
||||||
|
return directions[i];
|
||||||
|
}
|
||||||
|
function prevDir(dir: Dir): Dir {
|
||||||
|
const directions = [Dir.Up, Dir.Right, Dir.Down, Dir.Left];
|
||||||
|
const i = directions.indexOf(dir) - 1;
|
||||||
|
if (i < 0) {
|
||||||
|
return directions[directions.length - 1];
|
||||||
|
}
|
||||||
|
return directions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function printMap(path: Array<Coord> = []) {
|
||||||
|
const mapClone = map.slice().map((row: Array<string|number>) => row.slice());
|
||||||
|
path.forEach(({ x, y }) => {
|
||||||
|
mapClone[y][x] = 'O';
|
||||||
|
});
|
||||||
|
console.log(mapClone.map((row: Array<string|number>) => row.map((c) => typeof c === 'number' ? '.' : c).join('')).join("\n"));
|
||||||
|
console.log("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
function nextCoord(pos: Coord, direction: Dir): Coord {
|
||||||
|
return direction === Dir.Up ? { x: pos.x, y: pos.y - 1 }
|
||||||
|
: (direction === Dir.Right ? { x: pos.x + 1, y: pos.y }
|
||||||
|
: (direction === Dir.Down ? { x: pos.x, y: pos.y + 1 } : { x: pos.x - 1, y: pos.y })
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function isDeadEnd(pos: Coord): boolean {
|
||||||
|
if ((pos.x === 0 && pos.y === 0) || (pos.x === width - 1 && pos.y === width - 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const adjs = [Dir.Up, Dir.Right, Dir.Down, Dir.Left].map((dir) => get(nextCoord(pos, dir))).join('');
|
||||||
|
return adjs === '###.'
|
||||||
|
|| adjs === '##.#'
|
||||||
|
|| adjs === '#.##'
|
||||||
|
|| adjs === '.###';
|
||||||
|
}
|
||||||
|
|
||||||
|
function fillDeadEnd(pos: Coord): void {
|
||||||
|
set(pos, '#')
|
||||||
|
for (let dir of [Dir.Up, Dir.Right, Dir.Down, Dir.Left]) {
|
||||||
|
const next = nextCoord(pos, dir);
|
||||||
|
if (get(next) === '.') {
|
||||||
|
if (isDeadEnd(next)) {
|
||||||
|
fillDeadEnd(next);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
printMap();
|
||||||
|
|
||||||
|
for (let y = 0; y < height; y++) {
|
||||||
|
for (let x = 0; x < width; x++) {
|
||||||
|
const pos = { x, y };
|
||||||
|
const char = get(pos);
|
||||||
|
if (char !== '.') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (isDeadEnd(pos)) {
|
||||||
|
fillDeadEnd(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
printMap();
|
||||||
|
|
||||||
|
for (let i = 1025; i < input.length; i++) {
|
||||||
|
const byte = input[i].split(',').map((c: string) => parseInt(c));
|
||||||
|
set({ x: byte[0], y: byte[1] }, '#');
|
||||||
|
|
||||||
|
for (let y = 0; y < height; y++) {
|
||||||
|
for (let x = 0; x < width; x++) {
|
||||||
|
const pos = { x, y };
|
||||||
|
let char = get(pos);
|
||||||
|
if (typeof char === 'number') {
|
||||||
|
set(pos, '.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let finished = false;
|
||||||
|
|
||||||
|
function getScoresAfterPosition(pos: Coord, dir: Dir, path: Array<Coord> = []): void {
|
||||||
|
if (finished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
[dir, nextDir(dir), prevDir(dir)].forEach((newDir, i) => {
|
||||||
|
if (finished) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const next = nextCoord(pos, newDir);
|
||||||
|
if (next.x === width - 1 && next.y === height - 1) {
|
||||||
|
finished = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const nextCell = get(next);
|
||||||
|
if (nextCell !== '#' && (typeof nextCell !== 'number' || nextCell > path.length) && !path.find(({ x, y }) => next.x === x && next.y === y)) {
|
||||||
|
set(next, path.length);
|
||||||
|
getScoresAfterPosition(next, newDir, [...path, next]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
getScoresAfterPosition({ x: 0, y: 0 }, Dir.Right, [{ x: 0, y: 0 }]);
|
||||||
|
|
||||||
|
console.log(i, byte);
|
||||||
|
printMap();
|
||||||
|
if (!finished) {
|
||||||
|
console.log('blocked');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user