Big update: Adding all advent of codes to same repo
This commit is contained in:
18
AdventOfCode2022/src/days/Day1.ts
Normal file
18
AdventOfCode2022/src/days/Day1.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day1: DayFunc = (input) => {
|
||||
const elfFood: number[][] = input
|
||||
.split("\n\n")
|
||||
.map((i) => i.split("\n"))
|
||||
.map((i) => i.map((j) => parseInt(j)));
|
||||
|
||||
let highest = [0, 0, 0];
|
||||
elfFood.forEach((n) => {
|
||||
const h = n.reduce((prev, current) => (current += prev));
|
||||
const index = highest.findIndex(v => v < h);
|
||||
if (index !== -1) highest[index] = h;
|
||||
highest.sort();
|
||||
});
|
||||
|
||||
return [highest[0], highest.reduce((p, c) => c += p)];
|
||||
};
|
||||
42
AdventOfCode2022/src/days/Day10.ts
Normal file
42
AdventOfCode2022/src/days/Day10.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day10: DayFunc = (input) => {
|
||||
const parsed = input.trim().split('\n').map(v => {
|
||||
const s = v.split(' ');
|
||||
if (s.length === 1) return [s[0]];
|
||||
return [s[0], parseInt(s[1])];
|
||||
});
|
||||
|
||||
let x = 1;
|
||||
let cycles: number[] = [x];
|
||||
|
||||
parsed.forEach(i => {
|
||||
if (i[0] === "noop") {
|
||||
cycles.push(x);
|
||||
} else {
|
||||
cycles.push(x);
|
||||
cycles.push(x);
|
||||
x += i[1] as number;
|
||||
}
|
||||
});
|
||||
|
||||
const part1 = cycles[20] * 20 + cycles[60] * 60 + cycles[100] * 100 + cycles[140] * 140 + cycles[180] * 180 + cycles[220] * 220;
|
||||
|
||||
let outStr = "";
|
||||
for (let i = 1; i < cycles.length; i++) {
|
||||
|
||||
if ((i - 1) % 40 === 0) {
|
||||
outStr += '\n';
|
||||
}
|
||||
|
||||
if (cycles[i] === (i - 1) % 40 || cycles[i] === (i - 2) % 40 || cycles[i] === i % 40) {
|
||||
outStr += '#';
|
||||
} else {
|
||||
outStr += '.';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
console.log(outStr);
|
||||
return [part1, 0];
|
||||
}
|
||||
103
AdventOfCode2022/src/days/Day11.ts
Normal file
103
AdventOfCode2022/src/days/Day11.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type MonkeyList = Record<
|
||||
number,
|
||||
{
|
||||
inspected: number;
|
||||
items: string[];
|
||||
operation: string;
|
||||
test: number;
|
||||
ifTrue: number;
|
||||
ifFalse: number;
|
||||
}
|
||||
>;
|
||||
|
||||
const Hcf = (a: number, b: number): number => {
|
||||
let larger = a > b ? a : b;
|
||||
let smaller = a > b ? b : a;
|
||||
|
||||
let r = -1;
|
||||
|
||||
while (true) {
|
||||
if (larger % smaller === 0) break;
|
||||
r = larger % smaller;
|
||||
larger = smaller;
|
||||
smaller = r;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
export const Day11: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n\n")
|
||||
.map((v) => v.split("\n").map((i) => i.trim()));
|
||||
const list: MonkeyList = parsed.reduce((prev, next) => {
|
||||
const num = next[0].split(" ")[1].slice(0, -1);
|
||||
const items = next[1]
|
||||
.split(" ")
|
||||
.slice(2)
|
||||
.map((i) => i.replace(",", ""));
|
||||
const op = next[2].split("new = old ")[1];
|
||||
const test = parseInt(next[3].split(" ").pop());
|
||||
const ifTrue = parseInt(next[4].split(" ").pop());
|
||||
const ifFalse = parseInt(next[5].split(" ").pop());
|
||||
prev[num] = {
|
||||
items: items,
|
||||
operation: op,
|
||||
test: test,
|
||||
ifTrue: ifTrue,
|
||||
ifFalse: ifFalse,
|
||||
inspected: 0,
|
||||
};
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
const part1List: MonkeyList = JSON.parse(JSON.stringify(list));
|
||||
const part2List: MonkeyList = JSON.parse(JSON.stringify(list));
|
||||
|
||||
for (let round = 1; round <= 20; round++) {
|
||||
Object.values(part1List).forEach((v) => {
|
||||
v.items.forEach(old => {
|
||||
v.inspected++;
|
||||
let newVal = eval(`${old}${v.operation.replace('old', old.toString())}`);
|
||||
newVal = Math.floor(newVal / 3);
|
||||
if (newVal % v.test === 0) {
|
||||
part1List[v.ifTrue].items.push(newVal);
|
||||
} else {
|
||||
part1List[v.ifFalse].items.push(newVal);
|
||||
}
|
||||
});
|
||||
v.items = [];
|
||||
});
|
||||
}
|
||||
|
||||
const part1 = Object.values(part1List).map(v => v.inspected).sort((a, b) => b - a);
|
||||
const product = Object.values(part2List).reduce((p, v) => p * v.test, 1);
|
||||
|
||||
for (let round = 0; round < 10000; round++) {
|
||||
|
||||
Object.values(part2List).forEach((v) => {
|
||||
v.inspected += v.items.length;
|
||||
v.items.forEach(old => {
|
||||
let newVal = eval(`${old}${v.operation.replace('old', old.toString())}`);
|
||||
if (newVal > product) {
|
||||
newVal = newVal % product;
|
||||
}
|
||||
if (newVal % v.test === 0) {
|
||||
part2List[v.ifTrue].items.push(newVal);
|
||||
} else {
|
||||
part2List[v.ifFalse].items.push(newVal);
|
||||
}
|
||||
});
|
||||
v.items = [];
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
const part2 = Object.values(part2List).map(v => v.inspected).sort((a, b) => b - a);
|
||||
console.log(part2);
|
||||
|
||||
return [part1[0] * part1[1], part2[0] * part2[1]];
|
||||
};
|
||||
132
AdventOfCode2022/src/days/Day12.ts
Normal file
132
AdventOfCode2022/src/days/Day12.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const FunnyCharCode = (input: string): number => {
|
||||
if (input === "S") return "a".charCodeAt(0);
|
||||
if (input === "E") return "z".charCodeAt(0);
|
||||
return input.charCodeAt(0);
|
||||
};
|
||||
|
||||
const IsOk = (
|
||||
input: string[][],
|
||||
edges: Record<string, string[]>,
|
||||
a: [number, number],
|
||||
b: [number, number]
|
||||
) => {
|
||||
if (!edges[`${a[0]},${a[1]}`]) {
|
||||
edges[`${a[0]},${a[1]}`] = [];
|
||||
}
|
||||
const c = edges[`${a[0]},${a[1]}`];
|
||||
if (FunnyCharCode(input[a[0]][a[1]]) - FunnyCharCode(input[b[0]][b[1]]) >= -1) {
|
||||
c.push(`${b[0]},${b[1]}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const Day12: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) => i.split(""));
|
||||
|
||||
const edges: Record<string, string[]> = {};
|
||||
const visited: { letter: string; node: string; visited: boolean }[] = [];
|
||||
|
||||
for (let i = 0; i < parsed.length; i++) {
|
||||
for (let j = 0; j < parsed[0].length; j++) {
|
||||
visited.push({
|
||||
letter: parsed[i][j],
|
||||
node: `${i},${j}`,
|
||||
visited: false,
|
||||
});
|
||||
if (i > 0 && j > 0 && i < parsed.length - 1 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i > 0 && j > 0 && i < parsed.length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i > 0 && j > 0 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (i === 0 && j > 0 && j < parsed[0].length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
IsOk(parsed, edges, [i, j], [i, j - 1]);
|
||||
} else if (j === 0 && i > 0 && i < parsed.length - 1) {
|
||||
IsOk(parsed, edges, [i, j], [i + 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i - 1, j]);
|
||||
IsOk(parsed, edges, [i, j], [i, j + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IsOk(parsed, edges, [0, 0], [0, 1]);
|
||||
IsOk(parsed, edges, [0, 0], [1, 0]);
|
||||
|
||||
IsOk(
|
||||
parsed,
|
||||
edges,
|
||||
[parsed.length - 1, parsed[0].length - 1],
|
||||
[parsed.length - 1, parsed[0].length - 2]
|
||||
);
|
||||
IsOk(
|
||||
parsed,
|
||||
edges,
|
||||
[parsed.length - 1, parsed[0].length - 1],
|
||||
[parsed.length - 2, parsed[0].length - 1]
|
||||
);
|
||||
|
||||
IsOk(parsed, edges, [parsed.length - 1, 0], [parsed.length - 2, 0]);
|
||||
IsOk(parsed, edges, [parsed.length - 1, 0], [parsed.length - 1, 1]);
|
||||
|
||||
IsOk(parsed, edges, [0, parsed[0].length - 1], [0, parsed[0].length - 2]);
|
||||
IsOk(parsed, edges, [0, parsed[0].length - 1], [1, parsed[0].length - 1]);
|
||||
|
||||
const startNode = visited.find((v) => v.letter === "S");
|
||||
|
||||
const part1 = BFS(startNode.node, edges, visited);
|
||||
|
||||
const part2 = visited.filter(v => v.letter === 'a').map(n => BFS(n.node, edges, visited));
|
||||
|
||||
return [part1, Math.min(...part2)];
|
||||
};
|
||||
|
||||
const BFS = (
|
||||
currentNode: string,
|
||||
edges: Record<string, string[]>,
|
||||
visited: { letter: string; node: string; visited: boolean }[]
|
||||
): number => {
|
||||
const q: Array<{ letter: string; node: string; visited: boolean } | null> =
|
||||
[];
|
||||
|
||||
const marked = new Set();
|
||||
|
||||
const c = visited.find((v) => v.node === currentNode);
|
||||
q.push(c);
|
||||
|
||||
const depthQueue = [0];
|
||||
|
||||
marked.add(c.node);
|
||||
|
||||
while (q.length > 0) {
|
||||
const head = q.shift();
|
||||
const level = depthQueue.shift();
|
||||
|
||||
marked.add(head.node);
|
||||
|
||||
if (head.letter === "E") {
|
||||
return level;
|
||||
}
|
||||
|
||||
edges[head.node].filter(p => !marked.has(p)).forEach(v => {
|
||||
const n = visited.find(i => i.node === v);
|
||||
marked.add(n.node);
|
||||
q.push(n);
|
||||
depthQueue.push(level + 1);
|
||||
});
|
||||
}
|
||||
|
||||
return 10000000;
|
||||
};
|
||||
56
AdventOfCode2022/src/days/Day13.ts
Normal file
56
AdventOfCode2022/src/days/Day13.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const Compare = (a: any, b: any): "left" | "right" | null => {
|
||||
if (typeof a === "number" && typeof b === "number") {
|
||||
if (a < b) {
|
||||
return "right";
|
||||
} else if (a > b) {
|
||||
return "left";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (typeof a === "object" && typeof b === "object") {
|
||||
if (a.length === 0 && b.length > 0) return "right";
|
||||
if (b.length === 0 && a.length > 0) return "left";
|
||||
if (a.length === 0 && b.length === 0) return null;
|
||||
const ans = Compare(a[0], b[0]);
|
||||
if (ans !== null) return ans;
|
||||
|
||||
a.shift();
|
||||
b.shift();
|
||||
return Compare(a, b);
|
||||
} else if (typeof a === "object") {
|
||||
return Compare(a, [b]);
|
||||
} else if (typeof b === "object") {
|
||||
return Compare([a], b);
|
||||
}
|
||||
};
|
||||
|
||||
export const Day13: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n\n")
|
||||
.map((v) => v.split("\n").map((w) => JSON.parse(w)));
|
||||
|
||||
const part2Parsed = input.trim().replaceAll('\n\n', '\n').split('\n').map(v => JSON.parse(v));
|
||||
part2Parsed.push([[2]]);
|
||||
part2Parsed.push([[6]]);
|
||||
|
||||
let part1 = 0;
|
||||
parsed.forEach(([a, b], i) => {
|
||||
const side = Compare(a, b);
|
||||
if (side === "right") {
|
||||
part1 += i + 1;
|
||||
}
|
||||
});
|
||||
|
||||
part2Parsed.sort((a, b) => {
|
||||
if (Compare(JSON.parse(JSON.stringify(a)), JSON.parse(JSON.stringify(b))) === "left") return 1
|
||||
return -1;
|
||||
});
|
||||
|
||||
const two = part2Parsed.findIndex(i => JSON.stringify(i) === JSON.stringify([[2]])) + 1;
|
||||
const six = part2Parsed.findIndex(i => JSON.stringify(i) === JSON.stringify([[6]])) + 1;
|
||||
|
||||
return [part1, two * six];
|
||||
};
|
||||
178
AdventOfCode2022/src/days/Day14.ts
Normal file
178
AdventOfCode2022/src/days/Day14.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { DayFunc, UP } from "..";
|
||||
|
||||
const writer = Bun.stdout.writer();
|
||||
|
||||
const PrintGrid = async (g: string[][]) => {
|
||||
for (let i = 0; i < g.length; i++) {
|
||||
for (let j = 0; j < g[0].length; j++) {
|
||||
process.stdout.write(g[i][j]);
|
||||
}
|
||||
process.stdout.write('\n');
|
||||
}
|
||||
for (let i = 0; i < g.length; i++) {
|
||||
process.stdout.write(UP)
|
||||
}
|
||||
};
|
||||
|
||||
const EraseSand = ([x, y]: [number, number]) => {
|
||||
process.stdout.write(`\033[${y}B`);
|
||||
process.stdout.write(`\033[${x}C`);
|
||||
process.stdout.write('.');
|
||||
process.stdout.write(`\033[${y}A`);
|
||||
process.stdout.write(`\033[${x + 1}D`);
|
||||
}
|
||||
|
||||
const PrintSand = ([x, y]: [number, number]) => {
|
||||
process.stdout.write(`\033[${y}B`);
|
||||
process.stdout.write(`\033[${x}C`);
|
||||
process.stdout.write('+');
|
||||
process.stdout.write(`\033[${y}A`);
|
||||
process.stdout.write(`\033[${x + 1}D`);
|
||||
}
|
||||
|
||||
let minX = 0;
|
||||
let maxX = 0;
|
||||
let ySize = 0;
|
||||
|
||||
// Returns true if the sand has settled.
|
||||
const OneTick = (
|
||||
[y, x]: [number, number],
|
||||
grid: string[][]
|
||||
): [boolean, boolean, [number, number]] => {
|
||||
const next = grid[y + 1][x];
|
||||
|
||||
if (grid[y + 1][x] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
}
|
||||
|
||||
if (next === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x] = "+";
|
||||
return [false, false, [y + 1, x]];
|
||||
} else {
|
||||
|
||||
if (grid[y + 1][x - 1] === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x - 1] = "+";
|
||||
return [false, false, [y + 1, x - 1]];
|
||||
} else if (grid[y + 1][x - 1] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
} else if (grid[y + 1][x + 1] === ".") {
|
||||
grid[y][x] = ".";
|
||||
grid[y + 1][x + 1] = "+";
|
||||
return [false, false, [y + 1, x + 1]];
|
||||
} else if (grid[y + 1][x + 1] === undefined) {
|
||||
return [false, true, [0, 0]];
|
||||
} else {
|
||||
//Settled
|
||||
grid[y][x] = "o";
|
||||
return [true, false, [y, x]];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const Day14: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) =>
|
||||
i.split(" -> ").map((v) => v.split(",").map((w) => parseInt(w)))
|
||||
);
|
||||
|
||||
const xs = parsed.flatMap((v) => v).map((v) => v[0]);
|
||||
const ys = parsed.flatMap((v) => v).map((v) => v[1]);
|
||||
minX = Math.min(...xs);
|
||||
maxX = Math.max(...xs);
|
||||
const xSize = maxX - minX;
|
||||
ySize = Math.max(...ys);
|
||||
|
||||
let sand: [number, number] = [0, 500 - minX];
|
||||
|
||||
const grid = Array.from({ length: ySize + 1 }, (_) =>
|
||||
new Array(xSize + 1).fill(".")
|
||||
);
|
||||
parsed.forEach((rocks) => {
|
||||
for (let i = 0; i < rocks.length - 1; i++) {
|
||||
const [x1, y1] = rocks[i];
|
||||
const [x2, y2] = rocks[i + 1];
|
||||
if (x1 === x2) {
|
||||
const startY = Math.min(y1, y2);
|
||||
const endY = Math.max(y1, y2);
|
||||
for (let j = startY; j <= endY; j++) {
|
||||
grid[j][x1 - minX] = "#";
|
||||
}
|
||||
} else {
|
||||
const startX = Math.min(x1, x2) - minX;
|
||||
const endX = Math.max(x1, x2) - minX;
|
||||
for (let j = startX; j <= endX; j++) {
|
||||
grid[y1][j] = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
PrintGrid(grid);
|
||||
grid[sand[0]][sand[1]] = "+";
|
||||
|
||||
const increaseSize = 200;
|
||||
const part2Grid: string[][] = JSON.parse(JSON.stringify(grid));
|
||||
for (let i = 0; i < part2Grid.length; i++) {
|
||||
part2Grid[i] = [...Array(increaseSize).fill("."), ...part2Grid[i], ...Array(increaseSize).fill(".")];
|
||||
}
|
||||
|
||||
part2Grid.push(Array(xSize + increaseSize * 2 + 1).fill("."));
|
||||
part2Grid.push(Array(xSize + increaseSize * 2 + 1).fill("#"));
|
||||
|
||||
while (true) {
|
||||
Bun.sleepSync(0.01);
|
||||
const [settled, gameOver, newSand] = OneTick(sand, grid);
|
||||
EraseSand([sand[1], sand[0]]);
|
||||
|
||||
if (gameOver) {
|
||||
grid[sand[0]][sand[1]] = ".";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!settled) {
|
||||
sand = newSand;
|
||||
} else {
|
||||
sand = [0, 500 - minX];
|
||||
grid[sand[0]][sand[1]] = "+";
|
||||
}
|
||||
PrintSand([sand[1], sand[0]]);
|
||||
}
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
process.stdout.write('\n');
|
||||
}
|
||||
|
||||
const part1 = grid.reduce((p, n) => p + n.filter((i) => i === "o").length, 0);
|
||||
|
||||
minX = minX - increaseSize;
|
||||
ySize = ySize + 2;
|
||||
sand = [0, 500 - minX];
|
||||
while (true) {
|
||||
// Bun.sleepSync(0.001);
|
||||
// PrintGrid(part2Grid);
|
||||
const [settled, gameOver, newSand] = OneTick(sand, part2Grid);
|
||||
if (gameOver) {
|
||||
part2Grid[sand[0]][sand[1]] = ".";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!settled) {
|
||||
sand = newSand;
|
||||
} else {
|
||||
if (newSand[0] === 0 && newSand[1] === 500 - minX) {
|
||||
part2Grid[0][500 - minX] = 'o';
|
||||
break;
|
||||
}
|
||||
sand = [0, 500 - minX];
|
||||
part2Grid[sand[0]][sand[1]] = "+";
|
||||
}
|
||||
}
|
||||
for (let i = 0; i < grid.length; i++) {
|
||||
writer.write('\n');
|
||||
}
|
||||
const part2 = part2Grid.reduce((p, n) => p + n.filter((i) => i === "o").length, 0);
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
69
AdventOfCode2022/src/days/Day15.ts
Normal file
69
AdventOfCode2022/src/days/Day15.ts
Normal file
@@ -0,0 +1,69 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type Pos = { x: number; y: number };
|
||||
|
||||
export const Day15: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((v) => v.split(" at "))
|
||||
.map((v) => [v[1].slice(0, v[1].indexOf(":")), v[2]])
|
||||
.map((v) => v.map((i) => i.replaceAll(/[a-z]=/g, "").replaceAll(" ", "")))
|
||||
.map((v) => {
|
||||
const oneSplit = v[0].split(",");
|
||||
const twoSplit = v[1].split(",");
|
||||
return [
|
||||
[parseInt(oneSplit[0]), parseInt(oneSplit[1])],
|
||||
[parseInt(twoSplit[0]), parseInt(twoSplit[1])],
|
||||
];
|
||||
});
|
||||
const grid: Array<{ sensor: Pos; beacon: Pos; distance: number }> = [];
|
||||
|
||||
let smallestX = 10000;
|
||||
let largestX = 0;
|
||||
parsed.forEach((i) => {
|
||||
const dist = Math.abs(i[0][0] - i[1][0]) + Math.abs(i[0][1] - i[1][1]);
|
||||
if (i[0][0] < smallestX) smallestX = i[0][0];
|
||||
if (i[1][0] < smallestX) smallestX = i[1][0];
|
||||
|
||||
if (i[0][0] > largestX) largestX = i[0][0];
|
||||
if (i[1][0] > largestX) largestX = i[1][0];
|
||||
|
||||
grid.push({
|
||||
sensor: {
|
||||
x: i[0][0],
|
||||
y: i[0][1],
|
||||
},
|
||||
beacon: {
|
||||
x: i[1][0],
|
||||
y: i[1][1],
|
||||
},
|
||||
distance: dist,
|
||||
});
|
||||
});
|
||||
|
||||
const y = 10;
|
||||
let part1 = 0;
|
||||
console.log(smallestX);
|
||||
console.log(largestX);
|
||||
for (let i = smallestX - 10000000; i <= largestX + 10000000; i++) {
|
||||
const testPos: Pos = {
|
||||
x: i,
|
||||
y: y,
|
||||
};
|
||||
|
||||
const beaconHere = grid.find(p => p.beacon.x === testPos.x && p.beacon.y === testPos.y);
|
||||
if (beaconHere) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const testPoint = grid.find(p => Math.abs(p.sensor.x - testPos.x) + Math.abs(p.sensor.y - testPos.y) <= p.distance);
|
||||
|
||||
|
||||
if (testPoint) {
|
||||
part1++;
|
||||
}
|
||||
}
|
||||
|
||||
return [part1, 0];
|
||||
};
|
||||
218
AdventOfCode2022/src/days/Day17.ts
Normal file
218
AdventOfCode2022/src/days/Day17.ts
Normal file
@@ -0,0 +1,218 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const blocks = [
|
||||
[["@", "@", "@", "@"]],
|
||||
[
|
||||
[".", "@", "."],
|
||||
["@", "@", "@"],
|
||||
[".", "@", "."],
|
||||
],
|
||||
[
|
||||
[".", ".", "@"],
|
||||
[".", ".", "@"],
|
||||
["@", "@", "@"],
|
||||
],
|
||||
[["@"], ["@"], ["@"], ["@"]],
|
||||
[
|
||||
["@", "@"],
|
||||
["@", "@"],
|
||||
],
|
||||
];
|
||||
|
||||
function PrintGrid(grid: string[][]) {
|
||||
for (let i = grid.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < grid[0].length; j++) {
|
||||
process.stdout.write(grid[i][j]);
|
||||
}
|
||||
process.stdout.write("\n");
|
||||
}
|
||||
process.stdout.write("++++++++++++++++++++++++++++\n");
|
||||
}
|
||||
|
||||
function MoveDown(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number]
|
||||
): boolean {
|
||||
// Moving through the floor.
|
||||
if (y - block.length + 1 === 0) return false;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@" && grid[y - i - 1][j + x] === "#") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision. Clear block.
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
y--;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "@";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function MoveSides(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number],
|
||||
unit: -1 | 1
|
||||
): boolean {
|
||||
// Goes off the sides
|
||||
if (x + unit < 0 || x + block[0].length + unit > grid[0].length) return false;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@" && grid[y - i][j + x + unit] === "#") {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No collision. Clear block.
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = ".";
|
||||
}
|
||||
}
|
||||
}
|
||||
x += unit;
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "@";
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function SettleBlock(
|
||||
grid: string[][],
|
||||
block: string[][],
|
||||
[x, y]: [number, number]
|
||||
) {
|
||||
for (let i = block.length - 1; i >= 0; i--) {
|
||||
for (let j = 0; j < block[0].length; j++) {
|
||||
if (block[i][j] === "@") {
|
||||
grid[y - i][j + x] = "#";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* BlockGen(start = 0, end = Infinity, step = 1) {
|
||||
for (let i = start; i < end; i += step) {
|
||||
yield { block: blocks[i % blocks.length]!, index: i % blocks.length };
|
||||
}
|
||||
}
|
||||
|
||||
function CalcHeight(grid: string[][]) {
|
||||
let e = 0;
|
||||
for (let i = grid.length - 1; i >= 0; i--) {
|
||||
if (grid[i].some((j) => j === "#")) {
|
||||
break;
|
||||
}
|
||||
e++;
|
||||
}
|
||||
return grid.length - e;
|
||||
}
|
||||
|
||||
export const Day17: DayFunc = (input) => {
|
||||
const parsed = input.trim().split("");
|
||||
const gen = BlockGen();
|
||||
|
||||
const grid: string[][] = [];
|
||||
let jet = 0;
|
||||
let part1: number;
|
||||
let addedOnHeight = 0;
|
||||
|
||||
const depthMap: Record<string, {height: number; index: number}> = {};
|
||||
|
||||
for (let i = 0; i < 1e12; i++) {
|
||||
if (i === 2022) {
|
||||
part1 = CalcHeight(grid);
|
||||
}
|
||||
|
||||
const g = gen.next().value;
|
||||
if (!g) return;
|
||||
const block = g.block;
|
||||
|
||||
// Not right, not necessarily the top row.
|
||||
let emptyRows = 0;
|
||||
let rock = -1;
|
||||
for (let c = grid.length - 1; c >= 0; c--) {
|
||||
if (grid[c].some((i) => i === "#")) {
|
||||
rock = c;
|
||||
break;
|
||||
}
|
||||
emptyRows++;
|
||||
}
|
||||
if (emptyRows < 3 + block.length) {
|
||||
for (let c = 0; c <= 2 + block.length - emptyRows; c++) {
|
||||
grid.push([".", ".", ".", ".", ".", ".", "."]);
|
||||
}
|
||||
}
|
||||
const topLeft: [number, number] = [2, rock + 3 + block.length];
|
||||
|
||||
for (let j = block.length - 1; j >= 0; j--) {
|
||||
const newRow = [".", ".", ...block[j]];
|
||||
for (let k = 0; k < 5 - block[j].length; k++) {
|
||||
newRow.push(".");
|
||||
}
|
||||
grid[rock === -1 ? 3 - j : block.length - j + rock + 3] = newRow;
|
||||
}
|
||||
|
||||
let movedDown = true;
|
||||
do {
|
||||
if (parsed[jet % parsed.length] === "<") {
|
||||
const moved = MoveSides(grid, block, topLeft, -1);
|
||||
if (moved) topLeft[0]--;
|
||||
} else {
|
||||
const moved = MoveSides(grid, block, topLeft, 1);
|
||||
if (moved) topLeft[0]++;
|
||||
}
|
||||
jet++;
|
||||
movedDown = MoveDown(grid, block, topLeft);
|
||||
if (movedDown) {
|
||||
topLeft[1]--;
|
||||
}
|
||||
} while (movedDown);
|
||||
SettleBlock(grid, block, topLeft);
|
||||
|
||||
const depth = [0, 0, 0, 0, 0, 0, 0];
|
||||
for (let x = 0; x < 7; x++) {
|
||||
for (let y = grid.length - 1; y >= 0; y--) {
|
||||
if (grid[y][x] === '#') {
|
||||
depth[x] = grid.length - y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
const key = `${g.index},${jet % parsed.length},${JSON.stringify(depth)}`;
|
||||
if (key in depthMap) {
|
||||
const height = CalcHeight(grid);
|
||||
const mapEntry = depthMap[key];
|
||||
const diff = height - mapEntry.height;
|
||||
const cycleNum = Math.floor((1e12 - i) / (i - mapEntry.index));
|
||||
i += cycleNum * (i - mapEntry.index);
|
||||
addedOnHeight += diff * cycleNum;
|
||||
} else {
|
||||
depthMap[key] = { height: CalcHeight(grid), index: i };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return [part1, CalcHeight(grid) + addedOnHeight];
|
||||
};
|
||||
31
AdventOfCode2022/src/days/Day18.ts
Normal file
31
AdventOfCode2022/src/days/Day18.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
function CalcDist(
|
||||
[x1, y1, z1]: [number, number, number],
|
||||
[x2, y2, z2]: [number, number, number]
|
||||
): number {
|
||||
return Math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2 + (z1 - z2) ** 2);
|
||||
}
|
||||
|
||||
export const Day18: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((i) => i.split(",").map((j) => parseInt(j)));
|
||||
|
||||
let part1 = parsed.length * 6;
|
||||
for (let i = 0; i < parsed.length; i++) {
|
||||
const a = parsed[i];
|
||||
for (let j = 0; j < parsed.length; j++) {
|
||||
if (i === j) continue;
|
||||
const b = parsed[j];
|
||||
// @ts-ignore
|
||||
const dist = CalcDist(a, b);
|
||||
if (dist === 1) {
|
||||
part1--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [part1, 0];
|
||||
};
|
||||
70
AdventOfCode2022/src/days/Day2.ts
Normal file
70
AdventOfCode2022/src/days/Day2.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
// A = Rock, B = Paper, C = Scissors
|
||||
// X = Rock, Y = Paper, Z = Scissors
|
||||
// 1 = Rock, 2 = Paper, 3 = Scissors
|
||||
// 0 = Lose, 3 = Draw, 6 = Win
|
||||
type Options = 'r' | 'p' | 's';
|
||||
|
||||
const mapping: {[key: string]: Options} = {
|
||||
A: 'r',
|
||||
B: 'p',
|
||||
C: 's',
|
||||
X: 'r',
|
||||
Y: 'p',
|
||||
Z: 's',
|
||||
}
|
||||
|
||||
const scores: Record<
|
||||
Options,
|
||||
{
|
||||
score: number;
|
||||
beats: Options;
|
||||
loses: Options;
|
||||
}
|
||||
> = {
|
||||
'r': {
|
||||
score: 1,
|
||||
beats: "s",
|
||||
loses: "p",
|
||||
},
|
||||
'p': {
|
||||
score: 2,
|
||||
beats: "r",
|
||||
loses: "s",
|
||||
},
|
||||
's': {
|
||||
score: 3,
|
||||
beats: "p",
|
||||
loses: "r",
|
||||
},
|
||||
};
|
||||
|
||||
export const Day2: DayFunc = (input) => {
|
||||
const plays: string[][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((line) => line.split(" "));
|
||||
|
||||
let part1 = 0;
|
||||
let part2 = 0;
|
||||
|
||||
plays.forEach(([opp, you]) => {
|
||||
part1 += scores[mapping[you]].score;
|
||||
if (mapping[you] === mapping[opp]) {
|
||||
part1 += 3;
|
||||
} else if (scores[mapping[you]].beats === mapping[opp]) {
|
||||
part1 += 6;
|
||||
}
|
||||
|
||||
if (you === 'X') {
|
||||
part2 += scores[scores[mapping[opp]].beats].score;
|
||||
} else if (you === 'Y') {
|
||||
part2 += 3 + scores[mapping[opp]].score;
|
||||
} else {
|
||||
part2 += 6 + scores[scores[mapping[opp]].loses].score;
|
||||
}
|
||||
});
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
35
AdventOfCode2022/src/days/Day3.ts
Normal file
35
AdventOfCode2022/src/days/Day3.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const getCode = (x: Set<string>): number => {
|
||||
const code = x.values().next().value.charCodeAt(0);
|
||||
return code + (code <= 90 ? -38 : -96);
|
||||
};
|
||||
|
||||
export const Day3: DayFunc = (input) => {
|
||||
const bags: string[] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
|
||||
const part1Bags = bags.map((i) => [i.slice(0, i.length / 2), i.slice(i.length / 2)]);
|
||||
const part2Bags = []
|
||||
for (let i = 0; i < bags.length; i += 3) {
|
||||
part2Bags.push(bags.slice(i, i + 3));
|
||||
}
|
||||
|
||||
const part1 = part1Bags.reduce((prev, [c1, c2]) => {
|
||||
const set1 = new Set(c1);
|
||||
const set2 = new Set(c2);
|
||||
const n = new Set([...set1].filter((x) => set2.has(x)));
|
||||
return prev + getCode(n);
|
||||
}, 0);
|
||||
|
||||
const part2 = part2Bags.reduce((prev, [c1, c2, c3]) => {
|
||||
const set1 = new Set(c1);
|
||||
const set2 = new Set(c2);
|
||||
const set3 = new Set(c3);
|
||||
const n = new Set([...set1].filter((x) => set2.has(x)).filter(x => set3.has(x)));
|
||||
return prev + getCode(n as Set<string>);
|
||||
}, 0)
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
29
AdventOfCode2022/src/days/Day4.ts
Normal file
29
AdventOfCode2022/src/days/Day4.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day4: DayFunc = (input) => {
|
||||
const pairs: number[][][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((l) => l.split(",").map((p) => p.split("-").map((v) => parseInt(v))));
|
||||
|
||||
const [part1, part2] = pairs.reduce(
|
||||
([part1, part2], next) => {
|
||||
if (
|
||||
(next[0][0] <= next[1][0] && next[0][1] >= next[1][1]) ||
|
||||
(next[1][0] <= next[0][0] && next[1][1] >= next[0][1])
|
||||
) {
|
||||
part1++;
|
||||
part2++;
|
||||
} else if (
|
||||
(next[0][0] <= next[1][0] && next[1][0] <= next[0][1]) ||
|
||||
(next[1][0] <= next[0][0] && next[0][0] <= next[1][1])
|
||||
) {
|
||||
part2++;
|
||||
}
|
||||
return [part1, part2];
|
||||
},
|
||||
[0, 0]
|
||||
);
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
45
AdventOfCode2022/src/days/Day5.ts
Normal file
45
AdventOfCode2022/src/days/Day5.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
export const Day5: DayFunc = (input) => {
|
||||
let [inStacks, instructions] = input
|
||||
.split("\n\n")
|
||||
|
||||
const stacks = inStacks.split('\n')
|
||||
stacks.pop();
|
||||
|
||||
const numOfStacks = (stacks[0].length + 1) / 4;
|
||||
let realStacks = [...Array(numOfStacks)].map(() => []);
|
||||
|
||||
for (let i = 0; i < stacks.length; i++) {
|
||||
for (let j = 1; j < stacks[i].length; j += 4) {
|
||||
const c = stacks[i].charAt(j);
|
||||
const stackNum = (j - 1) / 4;
|
||||
if (c !== " ") {
|
||||
realStacks[stackNum].push(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
realStacks.map(s => s.reverse());
|
||||
const realStacks2 = [...realStacks].map(i => [...i]);
|
||||
|
||||
const rules = instructions.split('\n').map((i) => {
|
||||
const is = i.split(" ");
|
||||
return [parseInt(is[1]), parseInt(is[3]) - 1, parseInt(is[5]) - 1];
|
||||
});
|
||||
rules.pop();
|
||||
|
||||
rules.forEach(r => {
|
||||
for (let i = 0; i < r[0]; i++) {
|
||||
const popped = realStacks[r[1]].pop();
|
||||
realStacks[r[2]].push(popped);
|
||||
}
|
||||
|
||||
const crates = realStacks2[r[1]].splice(-r[0]);
|
||||
realStacks2[r[2]].push(...crates);
|
||||
});
|
||||
|
||||
const part1 = realStacks.reduce((prev, next) => prev + next[next.length - 1], "");
|
||||
const part2 = realStacks2.reduce((prev, next) => prev + next[next.length - 1], "");
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
21
AdventOfCode2022/src/days/Day6.ts
Normal file
21
AdventOfCode2022/src/days/Day6.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const FindRepeated = (input: string, gap: number): number => {
|
||||
for (let i = 0; i < input.length - gap; i++) {
|
||||
const sub = input.substring(i, i + gap);
|
||||
let changed = false;
|
||||
for (const c of sub) {
|
||||
if (sub.split(c).length > 2) {
|
||||
i += sub.indexOf(c);
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!changed) return i + gap;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
export const Day6: DayFunc = (input) => {
|
||||
return [FindRepeated(input, 4), FindRepeated(input, 14)];
|
||||
}
|
||||
92
AdventOfCode2022/src/days/Day7.ts
Normal file
92
AdventOfCode2022/src/days/Day7.ts
Normal file
@@ -0,0 +1,92 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type Node = {
|
||||
name: string;
|
||||
type: "file" | "dir";
|
||||
size: number;
|
||||
};
|
||||
|
||||
type Files = {
|
||||
[key: string]: { size: number; children: Node[] };
|
||||
};
|
||||
|
||||
const totalItems: Files = {};
|
||||
|
||||
const CalcSize = (dirName: string): number => {
|
||||
const dir = totalItems[dirName];
|
||||
let size = 0;
|
||||
for (const c of dir.children) {
|
||||
if (c.type === "file") {
|
||||
size += c.size;
|
||||
} else {
|
||||
size += CalcSize(c.name);
|
||||
}
|
||||
}
|
||||
dir.size = size;
|
||||
return size;
|
||||
};
|
||||
|
||||
export const Day7: DayFunc = (input) => {
|
||||
const parsed = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.filter((i) => i !== "$ ls").slice(1);
|
||||
|
||||
let path: string[] = [];
|
||||
let items: Node[] = [];
|
||||
|
||||
parsed.forEach((i) => {
|
||||
let pathReduced = "/";
|
||||
for (const c of path) {
|
||||
pathReduced += c + "/";
|
||||
}
|
||||
if (i === "$ cd ..") {
|
||||
if (!(pathReduced in totalItems)) {
|
||||
totalItems[pathReduced] = { size: 0, children: [...items] };
|
||||
items = [];
|
||||
}
|
||||
path.pop();
|
||||
} else if (i.charAt(0) === "$") {
|
||||
if (!(pathReduced in totalItems)) {
|
||||
totalItems[pathReduced] = { size: 0, children: [...items] };
|
||||
items = [];
|
||||
}
|
||||
path.push(i.split(" ")[2]);
|
||||
} else {
|
||||
const s = i.split(" ");
|
||||
items.push({
|
||||
type: s[0] === "dir" ? "dir" : "file",
|
||||
size: s[0] === "dir" ? 0 : parseInt(s[0]),
|
||||
name: s[0] === "dir" ? pathReduced + s[1] + "/" : s[1],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let pathReduced = "/";
|
||||
for (const c of path) {
|
||||
pathReduced += c + "/";
|
||||
}
|
||||
if (!(pathReduced in totalItems)) {
|
||||
totalItems[pathReduced] = { size: -1, children: [...items] };
|
||||
items = [];
|
||||
}
|
||||
|
||||
CalcSize("/");
|
||||
const part1 = Object.values(totalItems).reduce((p, n) => {
|
||||
if (n.size <= 100000) {
|
||||
return p + n.size;
|
||||
}
|
||||
return p;
|
||||
}, 0);
|
||||
|
||||
const usedSize = totalItems["/"].size;
|
||||
const toFree = 30000000 - (70000000 - usedSize);
|
||||
|
||||
const part2 = Object.entries(totalItems).map(v => {
|
||||
if (v[1].size > toFree) {
|
||||
return v[1].size;
|
||||
}
|
||||
}).filter(v => v).sort()[0];
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
57
AdventOfCode2022/src/days/Day8.ts
Normal file
57
AdventOfCode2022/src/days/Day8.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
const GetSmaller = (arr: number[], target: number): number => {
|
||||
let i = 0;
|
||||
for (; i < arr.length && arr[i] < target; i++) {}
|
||||
return i;
|
||||
};
|
||||
|
||||
const Part2 = (arr: number[], target: number): number => {
|
||||
const i = arr.findIndex(i => i >= target);
|
||||
if (i === -1) {
|
||||
return arr.length;
|
||||
}
|
||||
return i + 1;
|
||||
}
|
||||
|
||||
export const Day8: DayFunc = (input) => {
|
||||
const parsed: number[][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((v) => v.split("").map((i) => parseInt(i)));
|
||||
const transposed = parsed[0].map((_, colIndex) =>
|
||||
parsed.map((row) => row[colIndex])
|
||||
);
|
||||
|
||||
let part1 = parsed.length * 2 + parsed[0].length * 2 - 4;
|
||||
let part2 = 0;
|
||||
|
||||
for (let i = 1; i < parsed.length - 1; i++) {
|
||||
for (let j = 1; j < parsed[0].length - 1; j++) {
|
||||
const c = parsed[i][j];
|
||||
const row = parsed[i];
|
||||
const col = transposed[j];
|
||||
|
||||
const left = row.slice(0, j).reverse();
|
||||
const right = row.slice(j + 1);
|
||||
const top = col.slice(0, i).reverse();
|
||||
const bottom = col.slice(i + 1);
|
||||
|
||||
if (
|
||||
GetSmaller(left, c) === left.length ||
|
||||
GetSmaller(right, c) === right.length ||
|
||||
GetSmaller(top, c) === top.length ||
|
||||
GetSmaller(bottom, c) === bottom.length
|
||||
) {
|
||||
part1++;
|
||||
}
|
||||
|
||||
const view = Part2(left, c) * Part2(right, c) * Part2(top, c) * Part2(bottom, c);
|
||||
if (view > part2) {
|
||||
part2 = view;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [part1, part2];
|
||||
};
|
||||
71
AdventOfCode2022/src/days/Day9.ts
Normal file
71
AdventOfCode2022/src/days/Day9.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import { DayFunc } from "..";
|
||||
|
||||
type Pos = { x: number; y: number };
|
||||
|
||||
// Returns the non square rooted distance
|
||||
const CalcDist = (a: Pos, b: Pos) => {
|
||||
return (a.x - b.x) ** 2 + (a.y - b.y) ** 2;
|
||||
};
|
||||
|
||||
const CalcVisited = (snake: Pos[], parsed: [string, number][]): Record<string, number> => {
|
||||
|
||||
const visited: Record<string, number> = {};
|
||||
visited[JSON.stringify(snake[1])] = 1;
|
||||
|
||||
parsed.forEach(([direction, num]) => {
|
||||
for (let i = 0; i < num; i++) {
|
||||
if (direction === "R") snake[0].x++;
|
||||
else if (direction === "L") snake[0].x--;
|
||||
else if (direction === "U") snake[0].y++;
|
||||
else if (direction === "D") snake[0].y--;
|
||||
|
||||
for (let j = 1; j < snake.length; j++) {
|
||||
const t = snake[j];
|
||||
const h = snake[j - 1]
|
||||
const dist = CalcDist(h, t);
|
||||
if (dist === 4) {
|
||||
if (t.x === h.x) {
|
||||
t.y += (h.y < t.y) ? -1 : 1;
|
||||
} else if (t.y === h.y) {
|
||||
t.x += (h.x < t.x) ? -1 : 1;
|
||||
}
|
||||
} else if (dist === 5 || dist === 8) {
|
||||
t.x += (h.x > t.x) ? 1 : -1;
|
||||
t.y += (h.y > t.y) ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
const tailString = JSON.stringify(snake[snake.length - 1]);
|
||||
if (tailString in visited) {
|
||||
visited[tailString] = visited[tailString] + 1;
|
||||
} else {
|
||||
visited[tailString] = 1;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return visited;
|
||||
}
|
||||
|
||||
export const Day9: DayFunc = (input) => {
|
||||
const parsed: [string, number][] = input
|
||||
.trim()
|
||||
.split("\n")
|
||||
.map((v) => v.split(" "))
|
||||
.map(([a, b]) => [a, parseInt(b)]);
|
||||
|
||||
// 0th index is the head;
|
||||
const part1Snake: Pos[] = [
|
||||
{ x: 0, y: 0 },
|
||||
{ x: 0, y: 0 },
|
||||
];
|
||||
const part2Snake: Pos[] = [];
|
||||
for (let i = 0; i < 10; i++) {
|
||||
part2Snake.push({x: 0, y: 0});
|
||||
}
|
||||
|
||||
const part1 = CalcVisited(part1Snake, parsed)
|
||||
const part2 = CalcVisited(part2Snake, parsed)
|
||||
|
||||
return [Object.keys(part1).length, Object.keys(part2).length];
|
||||
};
|
||||
17
AdventOfCode2022/src/days/index.ts
Normal file
17
AdventOfCode2022/src/days/index.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export * from './Day1';
|
||||
export * from './Day2';
|
||||
export * from './Day3';
|
||||
export * from './Day4';
|
||||
export * from './Day5';
|
||||
export * from './Day6';
|
||||
export * from './Day7';
|
||||
export * from './Day8';
|
||||
export * from './Day9';
|
||||
export * from './Day10';
|
||||
export * from './Day11';
|
||||
export * from './Day12';
|
||||
export * from './Day13';
|
||||
export * from './Day14';
|
||||
export * from './Day15';
|
||||
export * from './Day17';
|
||||
export * from './Day18';
|
||||
Reference in New Issue
Block a user