Compare commits

...

13 Commits

Author SHA1 Message Date
dc8ec1ca17 Day 23 Part 2 2024-12-25 17:20:57 +00:00
eb0ae6d56b Day 25 Part 1 2024-12-25 15:41:07 +00:00
9f9b14fb7b Day 24 Part 2 Complete 2024-12-25 15:26:23 +00:00
97a0dad48d Day 24 Part 2 Attempt 2024-12-25 14:07:37 +00:00
b496e480b1 Day 24 Part 2 Attempt 2024-12-25 13:55:42 +00:00
fdc6260055 Day 24 Part 1 2024-12-24 10:13:53 +00:00
b9dd983a89 Day 22 and 23 2024-12-23 10:52:00 +00:00
4574a0f268 Day 21 Part 1 2024-12-22 11:36:29 +00:00
471c797821 Day 19 and 20 2024-12-20 13:26:37 +00:00
64d12de0f4 Day 18 2024-12-19 00:06:50 +00:00
f4e5be11bf Conflict 2024-12-18 23:24:08 +00:00
7b18064b75 Try A star algorithm 2024-12-18 23:22:08 +00:00
2dc097383c Try with branch caching again 2024-12-18 23:21:58 +00:00
12 changed files with 936 additions and 48 deletions

View File

@@ -106,8 +106,6 @@ for (let y = 1; y < height - 1; y++) {
let fastest: number|null = null;
const scoreCache: { [key: string]: [number, Coord, Dir] } = {};
const branchCache: { [key: string]: number } = {};
const scores: Array<[number, Array<string>]> = [];
@@ -125,9 +123,6 @@ function getScoresAfterPosition(pos: Coord, dir: Dir, currentScore = 0, path: Ar
} else {
branchCache[cacheKey] = currentScore;
}
if (lastBranch) {
scoreCache[`${lastBranch[1].x},${lastBranch[1].y}`] = [currentScore - lastBranch[0], pos, dir];
}
lastBranch = [currentScore, pos];
}
[dir, nextDir(dir), prevDir(dir)].forEach((newDir, i) => {

View File

@@ -14,7 +14,7 @@ enum Dir {
Left,
};
const map: Array<Array<string>> = [];
const map: Array<Array<string|number>> = [];
const width = 71;
const height = 71;
@@ -33,14 +33,14 @@ for (let i = 0; i < 1024; i++) {
map[y][x] = '#'
}
function get(pos: Coord): string {
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): void {
function set(pos: Coord, val: string|number): void {
map[pos.y][pos.x] = val;
}
@@ -58,9 +58,13 @@ function prevDir(dir: Dir): Dir {
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 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 {
@@ -93,7 +97,6 @@ function fillDeadEnd(pos: Coord): void {
};
}
printMap();
console.log("\n");
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
@@ -110,39 +113,38 @@ for (let y = 0; y < height; y++) {
printMap();
//let fastest: number|null = null;
//
//const scoreCache: { [key: string]: [number, Coord, Dir] } = {};
//
//const branchCache: { [key: string]: number } = {};
//
//const scores: Array<number> = [];
//
//function getScoresAfterPosition(pos: Coord, dir: Dir, path: Array<string> = []): void {
// if (fastest !== null && path.length >= fastest) {
// return;
// }
// [dir, nextDir(dir), prevDir(dir)].forEach((newDir, i) => {
// const next = nextCoord(pos, newDir);
// const nextStr = `${next.x},${next.y}`;
// if (!path.includes(nextStr)) {
// if (next.x === width - 1 && next.y === height - 1) {
// if (fastest === null || path.length < fastest) {
// fastest = path.length;
// }
// scores.push(path.length);
// return;
// } else if (next.x >= 0 && next. x < width && next.y >= 0 && next.y < height && get(next) === '.') {
// getScoresAfterPosition(next, newDir, [...path, nextStr]);
// }
// }
// });
//
// return;
//}
//
//getScoresAfterPosition({ x: 0, y: 0 }, Dir.Up, ['0,0']);
//
//console.log(scores);
//const fastestScore = Math.min(...scores);
//
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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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);