Compare commits
25 Commits
f3039370f9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| dc8ec1ca17 | |||
| eb0ae6d56b | |||
| 9f9b14fb7b | |||
| 97a0dad48d | |||
| b496e480b1 | |||
| fdc6260055 | |||
| b9dd983a89 | |||
| 4574a0f268 | |||
| 471c797821 | |||
| 64d12de0f4 | |||
| f4e5be11bf | |||
| 7b18064b75 | |||
| 2dc097383c | |||
|
|
f79cf1a347 | ||
| 058cdec540 | |||
|
|
a5c5acbad9 | ||
| 4dd516d9dc | |||
| ce848f3f16 | |||
| 61d4fdf795 | |||
| ccf47f1cc4 | |||
|
|
210475676a | ||
| ed25a377c7 | |||
|
|
2beaa0cdaa | ||
|
|
b6e4b27c7b | ||
|
|
8f6ca57372 |
@@ -4,34 +4,48 @@ const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
let stones: Array<string> = input.slice(0, -1).split(' ');
|
||||
|
||||
const countMap: { [key: string]: Array<number> } = {};
|
||||
|
||||
let sum = 0;
|
||||
|
||||
function splitStones(stones: Array<string>) {
|
||||
const newStones: Array<string> = [];
|
||||
stones.forEach((stone) => {
|
||||
if (stone === '0') {
|
||||
newStones.push('1');
|
||||
return;
|
||||
function getCountAfter(stone: string, blink: number, prev: Array<string> = []): number {
|
||||
const nextStep = blink - 1;
|
||||
if (countMap[stone]) {
|
||||
if (countMap[stone][nextStep]) {
|
||||
return countMap[stone][nextStep];
|
||||
}
|
||||
} else {
|
||||
countMap[stone] = [];
|
||||
}
|
||||
let newStones: Array<string>;
|
||||
if (stone === '0') {
|
||||
newStones = ['1'];
|
||||
} else {
|
||||
const len = stone.length;
|
||||
if (len % 2 === 0) {
|
||||
newStones.push(stone.slice(0, len / 2));
|
||||
let last = stone.slice(len / 2);
|
||||
newStones.push(''+(parseInt(last)));
|
||||
return;
|
||||
newStones = [stone.slice(0, len / 2), ''+parseInt(last)];
|
||||
} else {
|
||||
newStones = [''+(parseInt(stone) * 2024)];
|
||||
}
|
||||
newStones.push(''+(parseInt(stone) * 2024));
|
||||
});
|
||||
return newStones;
|
||||
}
|
||||
const len = newStones.length;
|
||||
countMap[stone][0] = len;
|
||||
if (blink === 1) {
|
||||
return len;
|
||||
} else {
|
||||
const newPrev = [...prev, stone];
|
||||
const len = newStones.reduce((carry, newStone) => carry + getCountAfter(newStone, nextStep, newPrev), 0);
|
||||
countMap[stone][nextStep] = len;
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
||||
let newStones = stones;
|
||||
const blinks = 75;
|
||||
|
||||
const blinks = 25;
|
||||
stones.forEach((stone) => {
|
||||
sum += getCountAfter(stone, blinks);
|
||||
});
|
||||
|
||||
for (let i = 0; i < blinks; i++) {
|
||||
newStones = splitStones(newStones);
|
||||
}
|
||||
|
||||
console.log(newStones.length);
|
||||
console.log(sum);
|
||||
|
||||
|
||||
90
2024/12/index.ts
Normal file
90
2024/12/index.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord { x: number, y: number };
|
||||
interface Plot { x: number, y: number, edges: number, corners: number };
|
||||
|
||||
const plots: Array<Array<string>> = input.split("\n").slice(0, -1).map((row: string) => row.split(''));
|
||||
|
||||
const height = plots.length;
|
||||
const width = plots[0].length;
|
||||
|
||||
const regions: Array<Array<Plot>> = [];
|
||||
|
||||
function getAllAdjacentPlots({ x, y }: Coord) {
|
||||
const letter = plots[y][x];
|
||||
plots[y][x] = '.' + letter;
|
||||
|
||||
const plot = { x, y, edges: 0, corners: 0 };
|
||||
|
||||
let adj: Array<Plot> = [plot];
|
||||
|
||||
let adjLetters: Array<string> = [];
|
||||
|
||||
[
|
||||
{ x, y: y - 1 },
|
||||
{ x: x + 1, y: y - 1 },
|
||||
{ x: x + 1, y },
|
||||
{ x: x + 1, y: y + 1 },
|
||||
{ x, y: y + 1 },
|
||||
{ x: x - 1, y: y + 1 },
|
||||
{ x: x - 1, y },
|
||||
{ x: x - 1, y: y - 1 },
|
||||
].forEach((adjCoord, i) => {
|
||||
const adjLetter = plots[adjCoord.y]
|
||||
&& plots[adjCoord.y][adjCoord.x];
|
||||
|
||||
if (i % 2 === 0) {
|
||||
if (adjLetter === letter) {
|
||||
adj = [...adj, ...getAllAdjacentPlots(adjCoord)];
|
||||
} else if (adjLetter !== '.' + letter) {
|
||||
plot.edges++;
|
||||
}
|
||||
}
|
||||
adjLetters.push(adjLetter ? adjLetter.replace('.', '') : '_');
|
||||
});
|
||||
|
||||
for (let i = 1; i < 8; i += 2) {
|
||||
let cornerLetter = adjLetters[i];
|
||||
let beforeLetter = adjLetters[i - 1];
|
||||
let afterLetter = adjLetters[i + 1] || adjLetters[0];
|
||||
if (cornerLetter === letter && (beforeLetter === letter || afterLetter === letter)) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
(beforeLetter === letter && afterLetter === letter)
|
||||
|| (beforeLetter !== letter && afterLetter !== letter)
|
||||
) {
|
||||
plot.corners++;
|
||||
}
|
||||
}
|
||||
|
||||
return adj;
|
||||
}
|
||||
|
||||
for (let y = 0; y < plots.length; y++) {
|
||||
const row = plots[y];
|
||||
for (let x = 0; x < row.length; x++) {
|
||||
const char = row[x];
|
||||
if (char.startsWith('.')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
regions.push(getAllAdjacentPlots({ x, y }));
|
||||
}
|
||||
}
|
||||
|
||||
let sum = 0;
|
||||
|
||||
regions.forEach((plots) => {
|
||||
const perim = plots.reduce((carry, { edges }) => carry + edges, 0);
|
||||
const vertices = plots.reduce((carry, { corners }) => carry + corners, 0);
|
||||
const area = plots.length;
|
||||
// Part 1
|
||||
// sum += perim * area;
|
||||
// Part 2
|
||||
sum += vertices * area;
|
||||
});
|
||||
|
||||
console.log(sum);
|
||||
55
2024/13/index.ts
Normal file
55
2024/13/index.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const lines = input.split("\n");
|
||||
|
||||
interface Coord { x: number, y: number };
|
||||
|
||||
interface equation {
|
||||
prize: Coord,
|
||||
a: Coord,
|
||||
b: Coord,
|
||||
}
|
||||
|
||||
const equations: Array<equation> = [];
|
||||
|
||||
for (let i = 0; i < lines.length; i += 4) {
|
||||
let match = lines[i].match(/Button A: X\+(\d+), Y\+(\d+)/);
|
||||
const a = { x: parseInt(match[1]), y: parseInt(match[2]) };
|
||||
match = lines[i + 1].match(/Button B: X\+(\d+), Y\+(\d+)/);
|
||||
const b = { x: parseInt(match[1]), y: parseInt(match[2]) };
|
||||
match = lines[i + 2].match(/Prize: X=(\d+), Y=(\d+)/);
|
||||
const prize = { x: parseInt(match[1]), y: parseInt(match[2]) };
|
||||
// Part 2
|
||||
prize.x += 10000000000000;
|
||||
prize.y += 10000000000000;
|
||||
|
||||
equations.push({ prize, a, b });
|
||||
}
|
||||
|
||||
let result = 0;
|
||||
|
||||
equations.forEach(({ a, b, prize }) => {
|
||||
// x*94 + y*22 = 8400
|
||||
// x*34 + y*67 = 5400
|
||||
// x = (8400 - y*22)/94
|
||||
// ((8400 - y*22)/94)*34 + y*67 = 5400
|
||||
// (8400 - y*22) + ((y*67*94)/34) = 5400 * 94/34
|
||||
// ((y*67*94)/34) - y*22 = ((5400 * 94/34)/34) - 8400
|
||||
// y * (((67*94)/34) - 22) = ((5400 * 94)/34) - 8400
|
||||
// y = (((5400 * 94)/34) - 8400) / (((67*94)/34) - 22)
|
||||
|
||||
const bPresses = (((prize.y * a.x) / a.y) - prize.x) / (((b.y * a.x) / a.y) - b.x);
|
||||
const aPresses = (prize.x - (bPresses * b.x)) / a.x;
|
||||
|
||||
if (
|
||||
Math.abs(bPresses - Math.round(bPresses)) < 0.001
|
||||
&& Math.abs(aPresses - Math.round(aPresses)) < 0.001
|
||||
&& aPresses > 0 && bPresses > 0
|
||||
) {
|
||||
result += (Math.round(aPresses) * 3) + Math.round(bPresses);
|
||||
}
|
||||
});
|
||||
|
||||
console.log(result);
|
||||
58
2024/14/index.ts
Normal file
58
2024/14/index.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
}
|
||||
|
||||
interface Bot {
|
||||
pos: Coord,
|
||||
vel: Coord,
|
||||
}
|
||||
|
||||
const bots: Array<Bot> = [];
|
||||
|
||||
input.split("\n").forEach((line: string) => {
|
||||
const matches = line.match(/p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)/);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
bots.push({
|
||||
pos: { x: parseInt(matches[1]), y: parseInt(matches[2]) },
|
||||
vel: { x: parseInt(matches[3]), y: parseInt(matches[4]) },
|
||||
});
|
||||
});
|
||||
|
||||
const width = 101;
|
||||
const height = 103;
|
||||
|
||||
const seconds = 100;
|
||||
|
||||
const quads = [0, 0, 0, 0];
|
||||
|
||||
bots.forEach((bot) => {
|
||||
let newX = (bot.pos.x + (bot.vel.x * seconds)) % width;
|
||||
if (newX < 0) {
|
||||
newX = width + newX;
|
||||
}
|
||||
bot.pos.x = newX;
|
||||
let newY = (bot.pos.y + (bot.vel.y * seconds)) % height;
|
||||
if (newY < 0) {
|
||||
newY = height + newY;
|
||||
}
|
||||
bot.pos.y = newY;
|
||||
if (newX < (width - 1) / 2 && newY < (height - 1) / 2) {
|
||||
quads[0]++;
|
||||
} else if (newX > (width - 1) / 2 && newY < (height - 1) / 2) {
|
||||
quads[1]++;
|
||||
} else if (newX < (width - 1) / 2 && newY > (height - 1) / 2) {
|
||||
quads[2]++;
|
||||
} else if (newX > (width - 1) / 2 && newY > (height - 1) / 2) {
|
||||
quads[3]++;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(quads);
|
||||
console.log(quads.reduce((c, n) => c * n, 1));
|
||||
80
2024/14/index2.ts
Normal file
80
2024/14/index2.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
}
|
||||
|
||||
interface Bot {
|
||||
pos: Coord,
|
||||
vel: Coord,
|
||||
}
|
||||
|
||||
const bots: Array<Bot> = [];
|
||||
|
||||
input.split("\n").forEach((line: string) => {
|
||||
const matches = line.match(/p=(-?\d+),(-?\d+) v=(-?\d+),(-?\d+)/);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
bots.push({
|
||||
pos: { x: parseInt(matches[1]), y: parseInt(matches[2]) },
|
||||
vel: { x: parseInt(matches[3]), y: parseInt(matches[4]) },
|
||||
});
|
||||
});
|
||||
|
||||
const width = 101;
|
||||
const height = 103;
|
||||
|
||||
let seconds = 0;
|
||||
|
||||
function printBots() {
|
||||
const botRows: Array<Array<string>> = [];
|
||||
for (let y = 0; y < height; y++) {
|
||||
botRows[y] = [];
|
||||
for (let x = 0; x < width; x++) {
|
||||
botRows[y][x] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
bots.forEach((bot) => {
|
||||
botRows[bot.pos.y][bot.pos.x] = '.';
|
||||
});
|
||||
|
||||
console.log(botRows.map((r) => r.join('')).join("\n"));
|
||||
console.log(seconds);
|
||||
}
|
||||
printBots();
|
||||
|
||||
function sleep() {
|
||||
const promise: Promise<void> = new Promise((resolve) => {
|
||||
setTimeout(() => resolve(), 100);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function go() {
|
||||
while (true) {
|
||||
seconds++;
|
||||
bots.forEach((bot) => {
|
||||
let newX = (bot.pos.x + (bot.vel.x)) % width;
|
||||
if (newX < 0) {
|
||||
newX = width + newX;
|
||||
}
|
||||
bot.pos.x = newX;
|
||||
let newY = (bot.pos.y + (bot.vel.y)) % height;
|
||||
if (newY < 0) {
|
||||
newY = height + newY;
|
||||
}
|
||||
bot.pos.y = newY;
|
||||
});
|
||||
if ((seconds - 72) % 103 === 0) {
|
||||
printBots();
|
||||
await sleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
go();
|
||||
89
2024/15/index.ts
Normal file
89
2024/15/index.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
const [mapStr, movementsStr] = input.split("\n\n");
|
||||
|
||||
const map: Array<Array<string>> = mapStr.split("\n").map((row: string) => row.split(''));
|
||||
const movements = movementsStr.split("\n").join('');
|
||||
|
||||
const width = map[0].length;
|
||||
const height = map.length;
|
||||
|
||||
const robotIndex = mapStr.indexOf('@');
|
||||
let robotPos = { x: robotIndex % (width + 1), y: Math.floor(robotIndex / height) };
|
||||
map[robotPos.y][robotPos.x] = '.';
|
||||
|
||||
function nextCoord(pos: Coord, dir: '^'|'>'|'<'|'v'): Coord|null {
|
||||
const newCoord = {
|
||||
"^": { x: pos.x, y: pos.y - 1 },
|
||||
">": { x: pos.x + 1, y: pos.y },
|
||||
"v": { x: pos.x, y: pos.y + 1 },
|
||||
"<": { x: pos.x - 1, y: pos.y },
|
||||
}[dir];
|
||||
|
||||
if (newCoord.x < 0 || newCoord.x >= width || newCoord.y < 0 || newCoord.y > height) {
|
||||
return null;
|
||||
}
|
||||
return newCoord;
|
||||
}
|
||||
|
||||
function printMap() {
|
||||
const mapClone = map.slice().map((row: Array<string>) => row.slice());
|
||||
mapClone[robotPos.y][robotPos.x] = '@';
|
||||
console.log(mapClone.map((row: Array<string>) => row.join('')).join("\n"));
|
||||
}
|
||||
|
||||
printMap();
|
||||
|
||||
for (let i = 0; i < movements.length; i++) {
|
||||
const direction = movements[i];
|
||||
|
||||
const nextRobotPosition = nextCoord(robotPos, direction);
|
||||
if (!nextRobotPosition) {
|
||||
continue;
|
||||
}
|
||||
let value = map[nextRobotPosition.y][nextRobotPosition.x];
|
||||
if (value === '#') {
|
||||
continue;
|
||||
}
|
||||
let boxes = [];
|
||||
let boxPos = {...nextRobotPosition};
|
||||
while (value === 'O') {
|
||||
boxes.push(boxPos);
|
||||
const nextBoxCoord = nextCoord(boxPos, direction);
|
||||
if (!nextBoxCoord) {
|
||||
break;
|
||||
}
|
||||
boxPos = nextBoxCoord;
|
||||
value = map[boxPos.y][boxPos.x];
|
||||
}
|
||||
if (boxes.length && value !== '#') {
|
||||
boxes.reverse().forEach((pos) => {
|
||||
map[pos.y][pos.x] = '.';
|
||||
const newPos = nextCoord(pos, direction)!;
|
||||
map[newPos.y][newPos.x] = 'O';
|
||||
})
|
||||
} else if (boxes.length) {
|
||||
continue;
|
||||
}
|
||||
robotPos = nextRobotPosition;
|
||||
printMap();
|
||||
}
|
||||
|
||||
let sum = 0;
|
||||
|
||||
map.forEach((row, y) => {
|
||||
row.forEach((val, x) => {
|
||||
if (val === 'O') {
|
||||
sum += ((y * 100) + x);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(sum);
|
||||
184
2024/15/index2.ts
Normal file
184
2024/15/index2.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
let [mapStr, movementsStr] = input.split("\n\n");
|
||||
mapStr = mapStr.replace(/([#.])/g, '$1$1').replaceAll('O', '[]').replaceAll('@', '@.');
|
||||
|
||||
const map: Array<Array<string>> = mapStr.split("\n").map((row: string) => row.split(''))
|
||||
const movements = movementsStr.split("\n").join('');
|
||||
|
||||
const width = map[0].length;
|
||||
const height = map.length;
|
||||
|
||||
const robotIndex = mapStr.indexOf('@');
|
||||
let robotPos = { x: robotIndex % (width + 1), y: Math.floor(robotIndex / width) };
|
||||
map[robotPos.y][robotPos.x] = '.';
|
||||
|
||||
function nextCoord(pos: Coord, dir: '^'|'>'|'<'|'v'): Coord {
|
||||
return {
|
||||
"^": { x: pos.x, y: pos.y - 1 },
|
||||
">": { x: pos.x + 1, y: pos.y },
|
||||
"v": { x: pos.x, y: pos.y + 1 },
|
||||
"<": { x: pos.x - 1, y: pos.y },
|
||||
}[dir];
|
||||
}
|
||||
|
||||
function printMap() {
|
||||
const mapClone = map.slice().map((row: Array<string>) => row.slice());
|
||||
mapClone[robotPos.y][robotPos.x] = '@';
|
||||
console.log(mapClone.map((row: Array<string>) => row.join('')).join("\n"));
|
||||
}
|
||||
|
||||
printMap();
|
||||
|
||||
function get(coord: Coord) {
|
||||
return map[coord.y][coord.x];
|
||||
}
|
||||
|
||||
function set(coord: Coord, val: string) {
|
||||
return map[coord.y][coord.x] = val;
|
||||
}
|
||||
|
||||
function canPushBox(leftPart: Coord, dir: '^'|'>'|'<'|'v'): boolean {
|
||||
if (dir === '<') {
|
||||
const next = nextCoord(leftPart, dir);
|
||||
const val = get(next);
|
||||
if (val === '#') {
|
||||
return false;
|
||||
}
|
||||
if (val === ']') {
|
||||
const movedNext = canPushBox(nextCoord(next, dir)!, dir);
|
||||
if (!movedNext) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const rightPart = nextCoord(leftPart, '>');
|
||||
if (dir === '>') {
|
||||
const next = nextCoord(rightPart, dir);
|
||||
const val = get(next);
|
||||
if (val === '#') {
|
||||
return false;
|
||||
}
|
||||
if (val === '[') {
|
||||
const movedNext = canPushBox(next, dir);
|
||||
if (!movedNext) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
const nextLeft = nextCoord(leftPart, dir);
|
||||
const nextRight = nextCoord(rightPart, dir);
|
||||
const nextLeftVal = get(nextLeft);
|
||||
const nextRightVal = get(nextRight);
|
||||
if (nextLeftVal === '#' || nextRightVal === '#') {
|
||||
return false;
|
||||
}
|
||||
if (nextLeftVal === '[' || nextLeftVal === ']') {
|
||||
const movedNext = canPushBox(nextLeftVal === '[' ? nextLeft : nextCoord(nextLeft, '<'), dir);
|
||||
if (!movedNext) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (nextRightVal === '[') {
|
||||
const movedNext = canPushBox(nextRight, dir);
|
||||
if (!movedNext) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function pushBox(leftPart: Coord, dir: '^'|'>'|'<'|'v') {
|
||||
if (dir === '<') {
|
||||
const next = nextCoord(leftPart, dir);
|
||||
const val = get(next);
|
||||
if (val === ']') {
|
||||
pushBox(nextCoord(next, dir)!, dir);
|
||||
}
|
||||
set(next, '[');
|
||||
set(leftPart, ']');
|
||||
set(nextCoord(leftPart, '>')!, '.');
|
||||
return;
|
||||
}
|
||||
const rightPart = nextCoord(leftPart, '>');
|
||||
if (dir === '>') {
|
||||
const next = nextCoord(rightPart, dir);
|
||||
const val = get(next);
|
||||
if (val === '[') {
|
||||
pushBox(next, dir);
|
||||
}
|
||||
set(rightPart, '[');
|
||||
set(next, ']');
|
||||
set(leftPart, '.');
|
||||
return;
|
||||
}
|
||||
const nextLeft = nextCoord(leftPart, dir);
|
||||
const nextRight = nextCoord(rightPart, dir);
|
||||
const nextLeftVal = get(nextLeft);
|
||||
const nextRightVal = get(nextRight);
|
||||
if (nextLeftVal === '[' || nextLeftVal === ']') {
|
||||
pushBox(nextLeftVal === '[' ? nextLeft : nextCoord(nextLeft, '<'), dir);
|
||||
}
|
||||
if (nextRightVal === '[') {
|
||||
pushBox(nextRight, dir);
|
||||
}
|
||||
set(nextLeft, '[');
|
||||
set(nextRight, ']');
|
||||
set(leftPart, '.');
|
||||
set(rightPart, '.');
|
||||
}
|
||||
|
||||
function sleep() {
|
||||
const promise: Promise<void> = new Promise((resolve) => {
|
||||
setTimeout(() => resolve(), 50);
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
async function go() {
|
||||
for (let i = 0; i < movements.length; i++) {
|
||||
const direction = movements[i];
|
||||
|
||||
const nextRobotPosition = nextCoord(robotPos, direction);
|
||||
let value = get(nextRobotPosition);
|
||||
if (value === '#') {
|
||||
printMap();
|
||||
continue;
|
||||
}
|
||||
if (value === '[' || value === ']') {
|
||||
const leftBoxCoord = value === '[' ? nextRobotPosition : nextCoord(nextRobotPosition, '<');
|
||||
if (canPushBox(leftBoxCoord, direction)) {
|
||||
pushBox(leftBoxCoord, direction);
|
||||
} else {
|
||||
printMap();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
robotPos = nextRobotPosition;
|
||||
printMap();
|
||||
await sleep();
|
||||
}
|
||||
|
||||
let sum = 0;
|
||||
|
||||
map.forEach((row, y) => {
|
||||
row.forEach((val, x) => {
|
||||
if (val === '[') {
|
||||
sum += ((y * 100) + x);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(sum);
|
||||
}
|
||||
|
||||
go();
|
||||
162
2024/16/index.ts
Normal file
162
2024/16/index.ts
Normal file
@@ -0,0 +1,162 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
enum Dir {
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left,
|
||||
};
|
||||
|
||||
const map: Array<Array<string>> = input.split("\n").map((row: string) => row.split(''));
|
||||
|
||||
const width = map[0].length;
|
||||
const height = map.length;
|
||||
|
||||
const snakeIndex = input.indexOf('S');
|
||||
let snakePos = { x: snakeIndex % (width + 1), y: Math.floor(snakeIndex / height) };
|
||||
let snakeDir = Dir.Right
|
||||
|
||||
function get(pos: Coord): string {
|
||||
return map[pos.y][pos.x];
|
||||
}
|
||||
|
||||
function set(pos: Coord, val: string): 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() {
|
||||
const mapClone = map.slice().map((row: Array<string>) => row.slice());
|
||||
console.log(mapClone.map((row: Array<string>) => row.join('')).join("\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 {
|
||||
const adjs = [Dir.Up, Dir.Right, Dir.Down, Dir.Left].map((dir) => get(nextCoord(pos, dir))).join('');
|
||||
return adjs === '###.'
|
||||
|| adjs === '##.#'
|
||||
|| adjs === '#.##'
|
||||
|| adjs === '.###';
|
||||
}
|
||||
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for (let y = 1; y < height - 1; y++) {
|
||||
for (let x = 1; x < width - 1; x++) {
|
||||
const pos = { x, y };
|
||||
const char = get(pos);
|
||||
if (char !== '.') {
|
||||
continue;
|
||||
}
|
||||
if (isDeadEnd(pos)) {
|
||||
fillDeadEnd(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let fastest: number|null = null;
|
||||
|
||||
const branchCache: { [key: string]: number } = {};
|
||||
|
||||
const scores: Array<[number, Array<string>]> = [];
|
||||
|
||||
function getScoresAfterPosition(pos: Coord, dir: Dir, currentScore = 0, path: Array<string> = [], lastBranch: [number, Coord]|null = null): void {
|
||||
if (fastest !== null && currentScore >= fastest) {
|
||||
return;
|
||||
}
|
||||
const branch = isBranch(pos, dir);
|
||||
if (branch) {
|
||||
const cacheKey = `${pos.x},${pos.y},${dir}`;
|
||||
const cache = branchCache[cacheKey];
|
||||
if (cache && cache < currentScore) {
|
||||
return;
|
||||
} else {
|
||||
branchCache[cacheKey] = currentScore;
|
||||
}
|
||||
lastBranch = [currentScore, pos];
|
||||
}
|
||||
[dir, nextDir(dir), prevDir(dir)].forEach((newDir, i) => {
|
||||
const next = nextCoord(pos, newDir);
|
||||
const nextStr = `${next.x},${next.y}`;
|
||||
if (!path.includes(nextStr)) {
|
||||
const add = i === 0 ? 1 : 1001;
|
||||
const score = currentScore + add;
|
||||
const nextChar = get(next);
|
||||
if (nextChar === 'E') {
|
||||
if (fastest === null || score < fastest) {
|
||||
fastest = score;
|
||||
}
|
||||
lastBranch = null;
|
||||
scores.push([score, [...path, nextStr]]);
|
||||
return;
|
||||
} else if (nextChar === '.') {
|
||||
getScoresAfterPosition(next, newDir, score, [...path, nextStr], branch ? [score, next] : lastBranch);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getScoresAfterPosition(snakePos, snakeDir);
|
||||
|
||||
const fastestScore = Math.min(...scores.map(([score]) => score));
|
||||
|
||||
let coordsOnPaths: Set<string> = new Set();
|
||||
scores.forEach(([score, path]) => {
|
||||
if (score === fastestScore) {
|
||||
path.forEach((coord) => coordsOnPaths.add(coord));
|
||||
}
|
||||
});
|
||||
|
||||
console.log(coordsOnPaths.size + 1);
|
||||
100
2024/17/index.ts
Normal file
100
2024/17/index.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const lines = input.split("\n");
|
||||
|
||||
let registerA = BigInt(parseInt(lines[0].split(' ')[2]));
|
||||
let registerB = BigInt(parseInt(lines[1].split(' ')[2]));
|
||||
let registerC = BigInt(parseInt(lines[2].split(' ')[2]));
|
||||
|
||||
let output: Array<string> = [];
|
||||
|
||||
let instructionsStr = lines[4].split(' ')[1];
|
||||
const instructions = instructionsStr.split(',').map((i: string) => parseInt(i));
|
||||
|
||||
let pointer = 0;
|
||||
|
||||
function combo(op: bigint): bigint {
|
||||
if (op <= 3n) {
|
||||
return op;
|
||||
}
|
||||
if (op === 4n) {
|
||||
return registerA;
|
||||
}
|
||||
if (op === 5n) {
|
||||
return registerB;
|
||||
}
|
||||
if (op === 6n) {
|
||||
return registerC;
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
function call(ins: number, op: number) {
|
||||
let bop = BigInt(op);
|
||||
if (ins === 0) {
|
||||
bop = combo(bop);
|
||||
registerA = registerA >> bop;
|
||||
return;
|
||||
}
|
||||
if (ins === 1) {
|
||||
registerB ^= bop;
|
||||
return;
|
||||
}
|
||||
if (ins === 2) {
|
||||
bop = combo(bop);
|
||||
registerB = bop & 7n;
|
||||
return;
|
||||
}
|
||||
if (ins === 4) {
|
||||
registerB ^= registerC;
|
||||
return;
|
||||
}
|
||||
if (ins === 5) {
|
||||
bop = combo(bop);
|
||||
output.push(''+(bop & 7n));
|
||||
return;
|
||||
}
|
||||
if (ins === 6) {
|
||||
bop = combo(bop);
|
||||
registerB = registerA >> bop;
|
||||
return;
|
||||
}
|
||||
if (ins === 7) {
|
||||
bop = combo(bop);
|
||||
registerC = registerA >> bop;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function printPC() {
|
||||
console.log(`
|
||||
A: ${registerA}
|
||||
B: ${registerB}
|
||||
C: ${registerC}
|
||||
|
||||
ins: ${typeof instructions[pointer] !== 'undefined' ? instructions[pointer] : 'NA'}
|
||||
op: ${typeof instructions[pointer+1] !== 'undefined' ? instructions[pointer+1] : 'NA'}
|
||||
combo: ${typeof instructions[pointer+1] !== 'undefined' ? combo(instructions[pointer+1]) : 'NA'}
|
||||
|
||||
Output: ${output}
|
||||
`);
|
||||
}
|
||||
|
||||
function run() {
|
||||
while (pointer < instructions.length) {
|
||||
const ins = instructions[pointer];
|
||||
const op = instructions[pointer + 1];
|
||||
|
||||
if (ins === 3) {
|
||||
pointer = registerA === 0n ? pointer + 2 : op;
|
||||
} else {
|
||||
call(ins, op);
|
||||
pointer += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
console.log(output.join(','));
|
||||
42
2024/17/index2.ts
Normal file
42
2024/17/index2.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const lines = input.split("\n");
|
||||
|
||||
let instructionsStr = lines[4].split(' ')[1];
|
||||
const instructions = instructionsStr.split(',').map((i: string) => parseInt(i));
|
||||
|
||||
function run(a: bigint) {
|
||||
return (((a & 7n) ^ 7n) ^ (a >> ((a & 7n) ^ 3n))) & 7n;
|
||||
}
|
||||
|
||||
let regA = 0n;
|
||||
|
||||
for (let i = instructions.length - 1; i >= 0; i--) {
|
||||
for (let a = 0n; a < 8n; a++) {
|
||||
const testA = (regA << 3n) + a;
|
||||
const out = run(testA);
|
||||
if (out === BigInt(instructions[i])) {
|
||||
regA = testA;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log(regA);
|
||||
|
||||
/*
|
||||
b = a % 8;
|
||||
b = b ^ 3;
|
||||
c = a / (2 ** b)
|
||||
a = a / 4
|
||||
b = b ^ 4
|
||||
b = b ^ c
|
||||
|
||||
x = (((a & 7) ^ 7) ^ (a / (2 ** ((a & 7) ^ 3)))) & 7
|
||||
*/
|
||||
|
||||
/*
|
||||
a = a >> 3
|
||||
x = a & 7
|
||||
*/
|
||||
150
2024/18/index.ts
Normal file
150
2024/18/index.ts
Normal file
@@ -0,0 +1,150 @@
|
||||
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();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
46
2024/19/index.ts
Normal file
46
2024/19/index.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8').split("\n");
|
||||
|
||||
const towels: Array<string> = input[0].split(', ');
|
||||
|
||||
const shortestTowel = Math.min(...towels.map((t: string) => t.length));
|
||||
const longestTowel = Math.max(...towels.map((t: string) => t.length));
|
||||
|
||||
const designs = input.slice(2);
|
||||
|
||||
let possible = 0;
|
||||
|
||||
let permSum = 0;
|
||||
|
||||
let patternMap: { [key: string]: number } = {};
|
||||
|
||||
function canBeDone(pattern: string): number {
|
||||
if (Object.hasOwn(patternMap, pattern)) {
|
||||
return patternMap[pattern];
|
||||
}
|
||||
let perms = 0;
|
||||
towels.forEach((t) => {
|
||||
if (t === pattern) {
|
||||
patternMap[pattern] = 1;
|
||||
perms++;
|
||||
} else if (pattern.startsWith(t)) {
|
||||
const subPerms = canBeDone(pattern.substring(t.length));
|
||||
perms += subPerms;
|
||||
}
|
||||
});
|
||||
patternMap[pattern] = perms;
|
||||
return perms;
|
||||
}
|
||||
|
||||
designs.forEach((d: string, i: number)=> {
|
||||
patternMap = {};
|
||||
console.log(Math.floor(i / designs.length * 100));
|
||||
const designPerms = canBeDone(d);
|
||||
if (designPerms) {
|
||||
possible++;
|
||||
permSum += designPerms;
|
||||
}
|
||||
});
|
||||
|
||||
console.log(possible, permSum);
|
||||
107
2024/20/index.ts
Normal file
107
2024/20/index.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
enum Dir {
|
||||
Up,
|
||||
Right,
|
||||
Down,
|
||||
Left,
|
||||
};
|
||||
|
||||
const map: Array<Array<string>> = input.split("\n").map((row: string) => row.split(''));
|
||||
|
||||
const width = map[0].length;
|
||||
const height = map.length;
|
||||
|
||||
const startIndex = input.indexOf('S');
|
||||
let startPos = { x: startIndex % (width + 1), y: Math.floor(startIndex / height) };
|
||||
|
||||
function get(pos: Coord): string {
|
||||
if (map[pos.y] && map[pos.y][pos.x]) {
|
||||
return map[pos.y][pos.x];
|
||||
}
|
||||
return '#';
|
||||
}
|
||||
|
||||
function set(pos: Coord, val: string): 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 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 })
|
||||
);
|
||||
}
|
||||
|
||||
const shortCuts: Array<number> = [];
|
||||
|
||||
const pathCoords: Array<Coord> = [startPos];
|
||||
|
||||
const cheatTime = 20;
|
||||
const minShortCut = 100;
|
||||
|
||||
let speedMap: { [key: string]: number } = {};
|
||||
|
||||
function findShortCuts(pos: Coord): void {
|
||||
for (let i = 0; i < pathCoords.length - minShortCut; i++) {
|
||||
const possibleSC = pathCoords[i];
|
||||
const dx = possibleSC.x - pos.x;
|
||||
const dy = possibleSC.y - pos.y;
|
||||
const cheatLength = Math.abs(dx) + Math.abs(dy);
|
||||
if (cheatLength <= cheatTime) {
|
||||
const shortCutLength = pathCoords.length - i - cheatLength;
|
||||
if (shortCutLength >= minShortCut) {
|
||||
shortCuts.push(shortCutLength);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let dir of [Dir.Up, Dir.Right, Dir.Down, Dir.Left]) {
|
||||
if (get(nextCoord(startPos, dir)) === '.') {
|
||||
let pos = startPos;
|
||||
loop:
|
||||
while (true) {
|
||||
for (let newDir of [dir, nextDir(dir), prevDir(dir)]) {
|
||||
const next = nextCoord(pos, newDir);
|
||||
const nextStr = `${next.x},${next.y}`;
|
||||
const nextChar = get(next);
|
||||
if (nextChar === 'E') {
|
||||
findShortCuts(next);
|
||||
pathCoords.push(next);
|
||||
break loop;
|
||||
} else if (nextChar === '.') {
|
||||
findShortCuts(next);
|
||||
pathCoords.push(next);
|
||||
pos = next;
|
||||
dir = newDir;
|
||||
break;
|
||||
}
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(shortCuts.length);
|
||||
134
2024/21/index.ts
Normal file
134
2024/21/index.ts
Normal file
@@ -0,0 +1,134 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
interface Coord {
|
||||
x: number,
|
||||
y: number,
|
||||
};
|
||||
|
||||
const keyPadMap: { [key: string]: Coord } = {
|
||||
A: { x: 2, y: 3 },
|
||||
'0': { x: 1, y: 3 },
|
||||
'1': { x: 0, y: 2 },
|
||||
'2': { x: 1, y: 2 },
|
||||
'3': { x: 2, y: 2 },
|
||||
'4': { x: 0, y: 1 },
|
||||
'5': { x: 1, y: 1 },
|
||||
'6': { x: 2, y: 1 },
|
||||
'7': { x: 0, y: 0 },
|
||||
'8': { x: 1, y: 0 },
|
||||
'9': { x: 2, y: 0 },
|
||||
};
|
||||
|
||||
const directionMap: { [key: string]: Coord } = {
|
||||
'<': { x: 0, y: 1 },
|
||||
'v': { x: 1, y: 1 },
|
||||
'>': { x: 2, y: 1 },
|
||||
'^': { x: 1, y: 0 },
|
||||
A: { x: 2, y: 0 },
|
||||
};
|
||||
|
||||
const permsMap: { [key: string]: Array<string> } = {
|
||||
'0,0': [],
|
||||
'0,1': ['Y'],
|
||||
'1,0': ['X'],
|
||||
'1,1': ['XY', 'YX'],
|
||||
'2,0': ['XX'],
|
||||
'2,1': ['XXY', 'YXX'],
|
||||
'2,2': ['XXYY', 'YYXX'],
|
||||
'0,2': ['YY'],
|
||||
'1,2': ['XYY', 'YYX'],
|
||||
'0,3': ['YYY'],
|
||||
'1,3': ['XYYY', 'YYYX'],
|
||||
'2,3': ['XXYYY', 'YYYXX'],
|
||||
};
|
||||
|
||||
function buttonsToPressCoords(from: Coord, to: Coord, forbidden: Coord): Array<string> {
|
||||
const dx = to.x - from.x;
|
||||
const dy = to.y - from.y;
|
||||
|
||||
if (dx === 0 && dy === 0) {
|
||||
return ['A'];
|
||||
}
|
||||
|
||||
const buttons: Array<Array<string>> = [];
|
||||
|
||||
const xArrow = dx < 0 ? '<' : '>';
|
||||
const yArrow = dy < 0 ? '^' : 'v';
|
||||
|
||||
const absX = Math.abs(dx);
|
||||
const absY = Math.abs(dy);
|
||||
const perms: Array<string> = permsMap[`${absX},${absY}`];
|
||||
|
||||
return perms.map((seq: string) => {
|
||||
return seq.split('').map((xy) => xy === 'X' ? xArrow : yArrow);
|
||||
}).filter((seq: Array<string>) => {
|
||||
let coord = { x: from.x, y: from.y };
|
||||
for (let arrow of seq) {
|
||||
if (arrow === '<') {
|
||||
coord.x--;
|
||||
} else if (arrow === '>') {
|
||||
coord.x++
|
||||
} else if (arrow === '^') {
|
||||
coord.y--;
|
||||
} else {
|
||||
coord.y++;
|
||||
}
|
||||
if (coord.x === forbidden.x && coord.y === forbidden.y) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}).map((seq) => [...seq, 'A'].join(''));
|
||||
}
|
||||
|
||||
function buttonsForSequence(start: Coord, seq: string, keyMap: { [key: string]: Coord }): Array<string> {
|
||||
let allPerms = [];
|
||||
const buttons = [];
|
||||
for (let ch of seq) {
|
||||
const to = keyMap[ch];
|
||||
const keyPerms = buttonsToPressCoords(start, to, keyMap === keyPadMap ? { x: 0, y: 3 } : { x: 0, y: 0 });
|
||||
allPerms.push(keyPerms);
|
||||
start = to;
|
||||
}
|
||||
return allPerms.reduce((buttons, perms) => {
|
||||
if (!buttons.length) {
|
||||
return perms;
|
||||
}
|
||||
if (!perms.length) {
|
||||
return buttons;
|
||||
}
|
||||
return buttons.flatMap((button) => {
|
||||
return perms.map((perm) => button + perm);
|
||||
});
|
||||
}, []);
|
||||
}
|
||||
|
||||
let sum = 0;
|
||||
|
||||
input.split("\n").forEach((seq: string) => {
|
||||
let buttons = buttonsForSequence(keyPadMap.A, seq, keyPadMap);
|
||||
for (let i = 0; i < 2; i++) {
|
||||
buttons = buttons.flatMap((seq) => {
|
||||
return buttonsForSequence(directionMap.A, seq, directionMap);
|
||||
});
|
||||
}
|
||||
|
||||
let shortestLength: number = buttons[0].length;
|
||||
let shortest = buttons[0];
|
||||
buttons.forEach((perm) => {
|
||||
if (perm.length < shortestLength) {
|
||||
shortestLength = perm.length;
|
||||
shortest = perm;
|
||||
}
|
||||
})
|
||||
|
||||
const seqNum = parseInt(seq.substring(-1));
|
||||
console.log(seq);
|
||||
console.log(shortest);
|
||||
console.log(seqNum, shortestLength);
|
||||
sum += (seqNum * shortestLength);
|
||||
});
|
||||
|
||||
console.log(sum);
|
||||
59
2024/22/index.ts
Normal file
59
2024/22/index.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
function createSecret(secret: bigint) {
|
||||
secret = ((secret << 6n) ^ secret) % 16777216n;
|
||||
secret = ((secret >> 5n) ^ secret) % 16777216n;
|
||||
return ((secret << 11n) ^ secret) % 16777216n;
|
||||
}
|
||||
|
||||
|
||||
let sum = 0n;
|
||||
|
||||
const changeMap: { [key: string]: Array<number> } = {};
|
||||
|
||||
input.split("\n").forEach((s: string, index: number) => {
|
||||
let seed = BigInt(parseInt(s));
|
||||
let seedStr = ''+seed;
|
||||
const changes = [];
|
||||
for (let i = 0; i < 2000; i++) {
|
||||
const newSeed = createSecret(seed);
|
||||
const newSeedStr = ''+newSeed;
|
||||
const lastDig = parseInt(newSeedStr[newSeedStr.length - 1]);
|
||||
const diff = lastDig - parseInt(seedStr[seedStr.length - 1]);
|
||||
changes.push(diff);
|
||||
if (i > 3) {
|
||||
changes.shift();
|
||||
const key = changes.join(',');
|
||||
if (!changeMap[key]) {
|
||||
changeMap[key] = [];
|
||||
}
|
||||
if (!changeMap[key][index]) {
|
||||
changeMap[key][index] = lastDig;
|
||||
}
|
||||
}
|
||||
seed = newSeed;
|
||||
seedStr = newSeedStr;
|
||||
}
|
||||
sum += seed;
|
||||
});
|
||||
|
||||
let highest: null|number = null;
|
||||
let highestSeq: null|string = null;
|
||||
|
||||
for (let seq in changeMap) {
|
||||
const prices = changeMap[seq];
|
||||
let priceSum = 0;
|
||||
prices.forEach((p) => {
|
||||
if (p) {
|
||||
priceSum += p;
|
||||
}
|
||||
});
|
||||
if (!highest || priceSum > highest) {
|
||||
highest = priceSum;
|
||||
highestSeq = seq;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(sum, highest, highestSeq);
|
||||
30
2024/23/index.ts
Normal file
30
2024/23/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const connections: { [key: string]: Array<string> }= {};
|
||||
|
||||
input.split("\n").forEach((conn: string) => {
|
||||
const [c1, c2] = conn.split('-');
|
||||
connections[c1] = [c2, ...(connections[c1] || [])]
|
||||
connections[c2] = [c1, ...(connections[c2] || [])]
|
||||
});
|
||||
|
||||
const tCs = new Set;
|
||||
|
||||
for (let key in connections) {
|
||||
const conns = connections[key];
|
||||
if (key.startsWith('t')) {
|
||||
conns.forEach((c2) => {
|
||||
connections[c2].forEach((c3) => {
|
||||
if (connections[c3].includes(key)) {
|
||||
const arr = [key, c2, c3];
|
||||
arr.sort();
|
||||
tCs.add(arr.join(','));
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
console.log(tCs, tCs.size);
|
||||
48
2024/23/index2.ts
Normal file
48
2024/23/index2.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const connections: { [key: string]: Array<string> }= {};
|
||||
|
||||
input.split("\n").forEach((conn: string) => {
|
||||
const [c1, c2] = conn.split('-');
|
||||
connections[c1] = [c2, ...(connections[c1] || [])]
|
||||
connections[c2] = [c1, ...(connections[c2] || [])]
|
||||
});
|
||||
|
||||
let nets: Set<string> = new Set;
|
||||
|
||||
for (let key in connections) {
|
||||
const conns = connections[key];
|
||||
conns.forEach((c2) => {
|
||||
connections[c2].forEach((c3) => {
|
||||
if (connections[c3].includes(key)) {
|
||||
const arr = [key, c2, c3];
|
||||
arr.sort();
|
||||
nets.add(arr.join(','));
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
while (nets.size > 1) {
|
||||
const nextNets: Set<string> = new Set;
|
||||
for (let net of nets) {
|
||||
const cps = net.split(',');
|
||||
for (let i in connections) {
|
||||
if (cps.includes(i)) {
|
||||
continue;
|
||||
}
|
||||
const conns = connections[i];
|
||||
if (cps.every((id) => conns.includes(id))) {
|
||||
const newNet = [...cps, i];
|
||||
newNet.sort();
|
||||
nextNets.add(newNet.join(','));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nets = nextNets;
|
||||
}
|
||||
|
||||
console.log(nets);
|
||||
54
2024/24/index.ts
Normal file
54
2024/24/index.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const [initStr, gatesStr] = input.split("\n\n");
|
||||
|
||||
const valMap: { [key: string]: number }= {};
|
||||
const gateMap: { [key: string]: [string, string, string] } = {};
|
||||
|
||||
const outputWires: Array<string> = [];
|
||||
|
||||
initStr.split("\n").forEach((s: string) => {
|
||||
const [wire, val] = s.split(': ');
|
||||
valMap[wire] = parseInt(val, 2);
|
||||
});
|
||||
|
||||
gatesStr.split("\n").forEach((s: string) => {
|
||||
const [inp, out] = s.split(' -> ');
|
||||
const [val1, op, val2] = inp.split(' ');
|
||||
gateMap[out] = [val1, op, val2];
|
||||
if (out.startsWith('z')) {
|
||||
outputWires.push(out);
|
||||
}
|
||||
});
|
||||
|
||||
function getWireVal(wire: string): number {
|
||||
if (Object.hasOwn(valMap, wire)) {
|
||||
return valMap[wire];
|
||||
}
|
||||
const val = getVal(...gateMap[wire])
|
||||
valMap[wire] = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
function getVal(wire1: string, op: string, wire2: string): number {
|
||||
const val1 = getWireVal(wire1);
|
||||
const val2 = getWireVal(wire2);
|
||||
|
||||
return {
|
||||
AND: () => val1 & val2,
|
||||
OR: () => val1 | val2,
|
||||
XOR: () => val1 ^ val2,
|
||||
}[op]!();
|
||||
}
|
||||
|
||||
outputWires.sort().reverse();
|
||||
|
||||
let outputStr = '';
|
||||
|
||||
outputWires.forEach((wire) => {
|
||||
outputStr += getWireVal(wire);
|
||||
});
|
||||
|
||||
console.log(outputStr, parseInt(outputStr, 2));
|
||||
206
2024/24/index2.ts
Normal file
206
2024/24/index2.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const [initStr, gatesStr] = input.split("\n\n");
|
||||
|
||||
const originalValMap: { [key: string]: number }= {};
|
||||
let valMap: { [key: string]: number } = {};
|
||||
const gateMap: { [key: string]: [string, string, string] } = {};
|
||||
|
||||
let xStr = '';
|
||||
let yStr = '';
|
||||
const outputWires: Array<string> = [];
|
||||
|
||||
initStr.split("\n").forEach((s: string) => {
|
||||
const [wire, val] = s.split(': ');
|
||||
originalValMap[wire] = parseInt(val, 2);
|
||||
if (wire.startsWith('x')) {
|
||||
xStr += val;
|
||||
} else {
|
||||
yStr += val;
|
||||
}
|
||||
});
|
||||
valMap = {...originalValMap};
|
||||
|
||||
const carries: Array<string> = [];
|
||||
const halfAdds: Array<string> = [];
|
||||
const badOuts: Array<string> = [];
|
||||
const badAnds: Array<string> = [];
|
||||
|
||||
const gates: Array<[string, string, string, string]> = gatesStr.split("\n").map((s: string) => {
|
||||
const [inp, out] = s.split(' -> ');
|
||||
const [val1, op, val2] = inp.split(' ');
|
||||
return [val1, op, val2, out];
|
||||
});
|
||||
gates.forEach(([val1, op, val2, out]) => {
|
||||
if (out[0] === 'z') {
|
||||
outputWires.push(out);
|
||||
}
|
||||
gateMap[out] = [val1, op, val2];
|
||||
});
|
||||
|
||||
function getWireVal(wire: string, trace: Array<string> = []): number {
|
||||
if (Object.hasOwn(valMap, wire)) {
|
||||
return valMap[wire];
|
||||
}
|
||||
const [wire1, op, wire2] = gateMap[wire];
|
||||
if (trace.includes(wire1) || trace.includes(wire2)) {
|
||||
throw Error('Cycle');
|
||||
}
|
||||
const val = getVal(wire1, op, wire2, [...trace, wire1, wire2]);
|
||||
valMap[wire] = val;
|
||||
return val;
|
||||
}
|
||||
|
||||
function getVal(wire1: string, op: string, wire2: string, trace: Array<string> = []): number {
|
||||
const val1 = getWireVal(wire1, trace);
|
||||
const val2 = getWireVal(wire2, trace);
|
||||
|
||||
return {
|
||||
AND: () => val1 & val2,
|
||||
OR: () => val1 | val2,
|
||||
XOR: () => val1 ^ val2,
|
||||
}[op]!();
|
||||
}
|
||||
|
||||
outputWires.sort();
|
||||
const expected = (parseInt(xStr, 2) + parseInt(yStr, 2)).toString(2);
|
||||
|
||||
function calculate() {
|
||||
let outputStr = '';
|
||||
valMap = {...originalValMap};
|
||||
outputWires.forEach((wire) => {
|
||||
outputStr += getWireVal(wire);
|
||||
});
|
||||
return outputStr;
|
||||
}
|
||||
|
||||
function swap(wire1: string, wire2: string): void {
|
||||
const wire1Gate = gateMap[wire1];
|
||||
const wire2Gate = gateMap[wire2];
|
||||
gateMap[wire1] = wire2Gate;
|
||||
gateMap[wire2] = wire1Gate;
|
||||
gates.forEach((gate) => {
|
||||
if (gate[3] === wire1) {
|
||||
gate[3] = wire2;
|
||||
} else if (gate[3] === wire2) {
|
||||
gate[3] = wire1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface HalfAdder {
|
||||
x: string,
|
||||
y: string,
|
||||
out: string,
|
||||
carry: string,
|
||||
sumGate: [string, string, string, string],
|
||||
carryGate: [string, string, string, string],
|
||||
}
|
||||
|
||||
interface FullAdder {
|
||||
x: string,
|
||||
y: string,
|
||||
carryIn: string,
|
||||
out: string,
|
||||
carry:string,
|
||||
halfSumGate: [string, string, string, string],
|
||||
fullSumGate: [string, string, string, string],
|
||||
sumCarryGate: [string, string, string, string],
|
||||
inputCarryGate: [string, string, string, string],
|
||||
carryGate: [string, string, string, string],
|
||||
}
|
||||
|
||||
const swaps: Array<string> = [];
|
||||
|
||||
function getGate(a: string, b: string, operator: string): [string, string, string, string] {
|
||||
const gate = gates.find(([val1, op, val2]) => {
|
||||
return op === operator
|
||||
&& (a === val1 || b === val2 || a === val2 || b === val1);
|
||||
});
|
||||
if (!gate) {
|
||||
throw new Error(`Two bad inputs, could not find gate, ${a}, ${b}`);
|
||||
}
|
||||
if ((gate[0] === a && gate[2] === b) || (gate[0] === b && gate[2] === a)) {
|
||||
return gate;
|
||||
}
|
||||
console.log(gate, a, b, operator);
|
||||
let wrongInput: string;
|
||||
let shouldBe: string;
|
||||
if (gate[0] === a) {
|
||||
wrongInput = b;
|
||||
shouldBe = gate[2]
|
||||
} else if (gate[0] === b) {
|
||||
wrongInput = a;
|
||||
shouldBe = gate[2]
|
||||
} if (gate[2] === a) {
|
||||
wrongInput = b;
|
||||
shouldBe = gate[0]
|
||||
} else {
|
||||
wrongInput = a;
|
||||
shouldBe = gate[0]
|
||||
}
|
||||
swaps.push(wrongInput);
|
||||
swaps.push(shouldBe);
|
||||
swap(wrongInput, shouldBe);
|
||||
|
||||
console.log(`Wrong input found, ${wrongInput} should be ${shouldBe}`)
|
||||
return gate;
|
||||
}
|
||||
|
||||
const carryGate = getGate('x00', 'y00', 'AND');
|
||||
const sumGate = getGate('x00', 'y00', 'XOR');
|
||||
const halfAdder: HalfAdder = {
|
||||
x: 'x00',
|
||||
y: 'y00',
|
||||
out: 'z00',
|
||||
carry: carryGate[3],
|
||||
carryGate: carryGate,
|
||||
sumGate: sumGate,
|
||||
}
|
||||
|
||||
console.log(halfAdder);
|
||||
|
||||
function getAdder(x: string, y: string, carryIn: string, out: string): FullAdder {
|
||||
const halfSumGate = getGate(x, y, 'XOR');
|
||||
const fullSumGate = getGate(halfSumGate[3], carryIn, 'XOR');
|
||||
if (fullSumGate[3] !== out) {
|
||||
console.log(`Wrong input found, ${fullSumGate[3]} should be ${out}`)
|
||||
swaps.push(fullSumGate[3]);
|
||||
swaps.push(out);
|
||||
swap(fullSumGate[3], out);
|
||||
}
|
||||
const sumCarryGate = getGate(halfSumGate[3], carryIn, 'AND');
|
||||
const inputCarryGate = getGate(x, y, 'AND')!;
|
||||
const carryGate = getGate(sumCarryGate[3], inputCarryGate[3], 'OR');
|
||||
return {
|
||||
x,
|
||||
y,
|
||||
carryIn,
|
||||
out: fullSumGate[3],
|
||||
carry: carryGate[3],
|
||||
halfSumGate,
|
||||
fullSumGate,
|
||||
sumCarryGate,
|
||||
inputCarryGate,
|
||||
carryGate
|
||||
};
|
||||
}
|
||||
|
||||
let carry = halfAdder.carry;
|
||||
|
||||
for (let out of outputWires) {
|
||||
if (out === 'z00' || out === 'z45') {
|
||||
continue;
|
||||
}
|
||||
const x = out.replace('z', 'x');
|
||||
const y = out.replace('z', 'y');
|
||||
|
||||
const adder = getAdder(x, y, carry, out);
|
||||
console.log(adder, swaps);
|
||||
carry = adder.carry;
|
||||
}
|
||||
|
||||
swaps.sort();
|
||||
console.log(swaps.join(','));
|
||||
44
2024/25/index.ts
Normal file
44
2024/25/index.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
const fs = require('fs');
|
||||
|
||||
const input = fs.readFileSync(__dirname + '/input.txt', 'utf8');
|
||||
|
||||
const keyLocks = input.split("\n\n");
|
||||
|
||||
const keys: number[][] = [];
|
||||
const locks: number[][] = [];
|
||||
|
||||
keyLocks.forEach((s: string) => {
|
||||
const rows = s.split("\n");
|
||||
const isKey = rows[0] === '.....';
|
||||
const columns: number[] = [-1, -1, -1, -1, -1];
|
||||
rows.forEach((row: string) => {
|
||||
for (let i = 0; i < row.length; i++) {
|
||||
if (row[i] === '#') {
|
||||
columns[i]++;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (isKey) {
|
||||
keys.push(columns);
|
||||
} else {
|
||||
locks.push(columns);
|
||||
}
|
||||
});
|
||||
|
||||
let matches = 0;
|
||||
|
||||
for (let lock of locks) {
|
||||
keyLoop:
|
||||
for (let key of keys) {
|
||||
for (let i in lock) {
|
||||
if (lock[i] + key[i] >= 6) {
|
||||
continue keyLoop;
|
||||
}
|
||||
}
|
||||
matches++;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(locks);
|
||||
console.log(keys);
|
||||
console.log(matches);
|
||||
Reference in New Issue
Block a user