diff --git a/2018/10/runner.ts b/2018/10/runner.ts new file mode 100644 index 0000000..b72c86b --- /dev/null +++ b/2018/10/runner.ts @@ -0,0 +1,29 @@ +import { readFile } from "fs/promises"; +import { taskOne, taskTwo } from "./task"; + +async function main() { + let lastArgument = process.argv.pop() as string; + let taskNumber = 1; + let isTest = false; + + if (lastArgument === "test") { + isTest = true; + taskNumber = parseInt(process.argv.pop() as string); + } else { + taskNumber = parseInt(lastArgument) + } + + const fileToLoad = isTest ? "test.in" : "solve.in"; + const fileContents = await readFile(fileToLoad, "utf-8") + + const lines = fileContents.split("\n"); + + if (taskNumber === 1) { + await taskOne(lines); + } + if (taskNumber === 2) { + await taskTwo(lines); + } +} + +void main(); \ No newline at end of file diff --git a/2018/10/task.ts b/2018/10/task.ts new file mode 100644 index 0000000..998f1ef --- /dev/null +++ b/2018/10/task.ts @@ -0,0 +1,102 @@ +export async function taskOne(input: string[]): Promise { + const points = input.map(i => { + const r = /[^<]*< *([-0-9]+), *([-0-9]+)>[^<]*< *([-0-9]+), *([-0-9]+)>/.exec(i)! + return { + x: Number(r[1]), + y: Number(r[2]), + vx: Number(r[3]), + vy: Number(r[4]) + } as Point + }) + + let t = 0 + while(true) { + const ps = getPointsAtTime(points, t) + let minY = Infinity + let maxY = -Infinity + + for (const p of ps) { + if (p.y < minY) minY = p.y + if (p.y > maxY) maxY = p.y + } + + if (maxY - minY < 10) { + console.log('T: ' + t) + print(ps) + break + } + + t++ + } +} + +export async function taskTwo(input: string[]): Promise { + const points = input.map(i => { + const r = /[^<]*< *([-0-9]+), *([-0-9]+)>[^<]*< *([-0-9]+), *([-0-9]+)>/.exec(i)! + return { + x: Number(r[1]), + y: Number(r[2]), + vx: Number(r[3]), + vy: Number(r[4]) + } as Point + }) + + let t = 0 + while(true) { + const ps = getPointsAtTime(points, t) + let minY = Infinity + let maxY = -Infinity + + for (const p of ps) { + if (p.y < minY) minY = p.y + if (p.y > maxY) maxY = p.y + } + + if (maxY - minY < 10) { + console.log(t) + break + } + + t++ + } +} + +interface Position { + x: number, y: number +} + +interface Point extends Position { + vx:number,vy: number +} + +function getPointsAtTime(ps: Point[], t: number): Position[] { + return ps.map(p => { + return { + x: p.x + t*p.vx, + y: p.y + t*p.vy + } + }) +} + +function print(ps: Position[]) { + let minX = Infinity + let maxX = -Infinity + let minY = Infinity + let maxY = -Infinity + + for (const p of ps) { + if (p.x < minX) minX = p.x + if (p.x > maxX) maxX = p.x + if (p.y < minY) minY = p.y + if (p.y > maxY) maxY = p.y + } + console.log(minX, maxX, minY, maxY) + + const g = Array.from({length:maxY-minY+1}, () => Array.from({length: maxX-minX+1}, () => false)) + + for (const p of ps) { + g[p.y-minY][p.x-minX] = true + } + + g.forEach(r => console.log(r.map(i => i ? '#' : ' ').join(''))) +} \ No newline at end of file diff --git a/2018/11/runner.ts b/2018/11/runner.ts new file mode 100644 index 0000000..b72c86b --- /dev/null +++ b/2018/11/runner.ts @@ -0,0 +1,29 @@ +import { readFile } from "fs/promises"; +import { taskOne, taskTwo } from "./task"; + +async function main() { + let lastArgument = process.argv.pop() as string; + let taskNumber = 1; + let isTest = false; + + if (lastArgument === "test") { + isTest = true; + taskNumber = parseInt(process.argv.pop() as string); + } else { + taskNumber = parseInt(lastArgument) + } + + const fileToLoad = isTest ? "test.in" : "solve.in"; + const fileContents = await readFile(fileToLoad, "utf-8") + + const lines = fileContents.split("\n"); + + if (taskNumber === 1) { + await taskOne(lines); + } + if (taskNumber === 2) { + await taskTwo(lines); + } +} + +void main(); \ No newline at end of file diff --git a/2018/11/task.ts b/2018/11/task.ts new file mode 100644 index 0000000..c6f663b --- /dev/null +++ b/2018/11/task.ts @@ -0,0 +1,94 @@ +export async function taskOne(input: string[]): Promise { + const serialNumber = Number(input[0]) + const L = 300 + + const grid = Array.from({length: L}, (_, x) => Array.from({length:L}, (_, y) => { + const rackID = x + 10 + 1 + let powerLevel = (rackID) * (y + 1) + powerLevel += serialNumber + powerLevel *= rackID + return { + rackID: rackID, + powerLevel: (Math.floor(powerLevel / 100)% 10)-5 + } as Cell + })) + + let maxP = [0,0] + let maxV = -Infinity + for (let x = 0; x < L-2; x++) { + for (let y = 0; y < L-2; y++) { + let s = 0 + for (let xd = 0; xd < 3; xd++) { + for (let yd = 0; yd < 3; yd++) { + s += grid[x+xd][y+yd].powerLevel + } + } + if (s > maxV) { + maxV = s + maxP = [x, y] + } + } + } + console.log(`${maxP[0]+1},${maxP[1]+1}`) + +} + +export async function taskTwo(input: string[]): Promise { + const serialNumber = Number(input[0]) + const L = 300 + + const grid = Array.from({length: L}, (_, x) => Array.from({length:L}, (_, y) => { + const rackID = x + 10 + 1 + let powerLevel = (rackID) * (y + 1) + powerLevel += serialNumber + powerLevel *= rackID + return (Math.floor(powerLevel / 100)% 10)-5 + })) + + const summedAreaTable = Array.from({length: L}, () => Array.from({length:L}, () => 0)) + + summedAreaTable[0][0] = grid[0][0] + for (let x = 1; x < L; x++) { + summedAreaTable[x][0] = summedAreaTable[x-1][0] + grid[x][0] + summedAreaTable[0][x] = summedAreaTable[0][x-1] + grid[0][x] + } + + for (let x = 1; x < L; x++) { + for (let y = 1; y < L; y++) { + summedAreaTable[x][y] = summedAreaTable[x-1][y] + summedAreaTable[x][y-1] - summedAreaTable[x-1][y-1] + grid[x][y] + } + } +/* + for (let y = 1; y < 10; y++) { + let r = '' + for (let x = 1; x < 10; x++) { + r += summedAreaTable[x][y] + ' ' + } + console.log(r) + }*/ + + function get(x1: number, x2: number, y1:number, y2: number) { + return summedAreaTable[x2][y2] + summedAreaTable[x1][y1] - summedAreaTable[x2][y1] - summedAreaTable[x1][y2] + } + + let maxP = [0,0, 0] + let maxV = -Infinity + for (let s = 1; s <= L; s++) { + for (let x = 0; x < L-s; x++) { + for (let y = 0; y < L-s; y++) { + let su = get(x, x+s, y, y+s) + if (su > maxV) { + maxV = su + maxP = [x, y, s] + } + } + } + } + + console.log(`${maxP[0]+2},${maxP[1]+2},${maxP[2]}`) +} + +interface Cell { + rackID: number, + powerLevel: number +} \ No newline at end of file diff --git a/2018/12/runner.ts b/2018/12/runner.ts new file mode 100644 index 0000000..b72c86b --- /dev/null +++ b/2018/12/runner.ts @@ -0,0 +1,29 @@ +import { readFile } from "fs/promises"; +import { taskOne, taskTwo } from "./task"; + +async function main() { + let lastArgument = process.argv.pop() as string; + let taskNumber = 1; + let isTest = false; + + if (lastArgument === "test") { + isTest = true; + taskNumber = parseInt(process.argv.pop() as string); + } else { + taskNumber = parseInt(lastArgument) + } + + const fileToLoad = isTest ? "test.in" : "solve.in"; + const fileContents = await readFile(fileToLoad, "utf-8") + + const lines = fileContents.split("\n"); + + if (taskNumber === 1) { + await taskOne(lines); + } + if (taskNumber === 2) { + await taskTwo(lines); + } +} + +void main(); \ No newline at end of file diff --git a/2018/12/task.ts b/2018/12/task.ts new file mode 100644 index 0000000..a963dc3 --- /dev/null +++ b/2018/12/task.ts @@ -0,0 +1,110 @@ +export async function taskOne(input: string[]): Promise { + let pots: Record = {} + let defaultState = false + function get(i: number) { + return pots[i] ?? defaultState + } + const init = input[0].split(': ')[1].split('') + for (let i = 0; i < init.length; i++) { + pots[i] = init[i] == '#' + } + let min = 0 + let max = init.length - 1 + + const rules: Record = {} + for (let i = 2; i < input.length; i++) { + const r = input[i].split(' => ') + rules[r[0]] = r[1] == '#' + } + + function getNew(i: number) { + let r = '' + for (let j = i-2; j <= i+2; j++) { + r += get(j) ? '#':'.' + } + return rules[r] ?? false + } + + for (let c = 0; c < 20; c++) { + const newState: Record = {} + for (let i = min-2; i <= max+2; i++) { + newState[i] = getNew(i) + } + min -= 2 + max += 2 + defaultState = rules[(defaultState ? '#' : '.').repeat(5)] + pots = newState + } + let c = 0 + for (let i = min; i <= max; i++) { + if (get(i)) c += i + } + console.log(c) +} + +export async function taskTwo(input: string[]): Promise { + let pots: Record = {} + let defaultState = false + function get(i: number) { + return pots[i] ?? defaultState + } + const init = input[0].split(': ')[1].split('') + for (let i = 0; i < init.length; i++) { + pots[i] = init[i] == '#' + } + let min = 0 + let max = init.length - 1 + + const rules: Record = {} + for (let i = 2; i < input.length; i++) { + const r = input[i].split(' => ') + rules[r[0]] = r[1] == '#' + } + + function getNew(i: number) { + let r = '' + for (let j = i-2; j <= i+2; j++) { + r += get(j) ? '#':'.' + } + return rules[r] ?? false + } + + function doSteps(C: number) { + for (let c = 0; c < C; c++) { + const newState: Record = {} + for (let i = min-2; i <= max+2; i++) { + newState[i] = getNew(i) + } + min -= 2 + max += 2 + defaultState = rules[(defaultState ? '#' : '.').repeat(5)] + pots = newState + } + } + doSteps(999) + const c1 = evalu() + doSteps(1) + const c2 = evalu() + + const GOAL = 50000000000 + const todo = GOAL - 1000 + const final = (c2-c1)*todo + c2 + console.log(c2, c1, c2-c1) + console.log(final) + + function evalu() { + let c = 0 + for (let i = min; i <= max; i++) { + if (get(i)) c += i + } + return c + } + + function print(min: number, max: number) { + let r = '' + for(let i = min; i <= max; i++) { + r += get(i) ? '#':'.' + } + console.log(r) + } +} \ No newline at end of file diff --git a/2018/13/runner.ts b/2018/13/runner.ts new file mode 100644 index 0000000..b72c86b --- /dev/null +++ b/2018/13/runner.ts @@ -0,0 +1,29 @@ +import { readFile } from "fs/promises"; +import { taskOne, taskTwo } from "./task"; + +async function main() { + let lastArgument = process.argv.pop() as string; + let taskNumber = 1; + let isTest = false; + + if (lastArgument === "test") { + isTest = true; + taskNumber = parseInt(process.argv.pop() as string); + } else { + taskNumber = parseInt(lastArgument) + } + + const fileToLoad = isTest ? "test.in" : "solve.in"; + const fileContents = await readFile(fileToLoad, "utf-8") + + const lines = fileContents.split("\n"); + + if (taskNumber === 1) { + await taskOne(lines); + } + if (taskNumber === 2) { + await taskTwo(lines); + } +} + +void main(); \ No newline at end of file diff --git a/2018/13/task.ts b/2018/13/task.ts new file mode 100644 index 0000000..1a3276b --- /dev/null +++ b/2018/13/task.ts @@ -0,0 +1,176 @@ +export async function taskOne(input: string[]): Promise { + interface Train { + x: number, y: number, xD: number, yD: number, turnState: number + } + const rails = input.map(i => i.split('')) + let trains: Train[] = [] + for (let y = 0; y < rails.length; y++) { + for (let x = 0; x < rails[y].length; x++) { + const t = rails[y][x] + if (['>', '<', '^', 'v'].includes(t)) { + if (rails[y][x-1] != ' ' && rails[y][x+1] != ' ') { + rails[y][x] = '-' + } else if (rails[y-1][x] != ' ' && rails[y+1][x] != ' ') { + rails[y][x] = '|' + } else { + throw x + ' | ' + y + } + const xD = t == '>' ? 1 : (t == '<' ? -1 : 0) + const yD = t == 'v' ? 1 : (t == '^' ? -1 : 0) + trains.push({x,y,xD,yD, turnState: 0}) + } + } + } + const posSet = new Set() + function addPos(x: number, y: number) { + posSet.add(x+'-'+y) + } + function delPos(x: number, y: number) { + posSet.delete(x+'-'+y) + }function hasPos(x: number, y: number) { + return posSet.has(x+'-'+y) + } + + let colided = false + while (!colided) { + trains = trains.sort((a,b) => { + if (a.y == b.y) { + return a.x < b.x ? -1:1 + } + return a.y < b.y ? -1:1 + }) + for (const t of trains) { + delPos(t.x,t.y) + t.x += t.xD + t.y += t.yD + if (hasPos(t.x,t.y)) { + console.log(t.x+','+t.y) + colided = true + break + } + addPos(t.x,t.y) + if (rails[t.y][t.x] == '+') { + const oXD = t.xD + switch(t.turnState) { + case 0: + t.xD = t.yD + t.yD = -oXD + break + case 2: + t.xD = -t.yD + t.yD = oXD + break + case 1: + default: + break + } + t.turnState = (t.turnState + 1) % 3 + } else if (rails[t.y][t.x] != '-' && rails[t.y][t.x] != '|') { + const oXD = t.xD + if (t.xD == 1 && rails[t.y][t.x] == '/' || t.xD == -1 && rails[t.y][t.x] == '/' + || t.yD == 1 && rails[t.y][t.x] == '\\' || t.yD == -1 && rails[t.y][t.x] == '\\' ) { + t.xD = t.yD + t.yD = -oXD + } else if (t.xD == 1 && rails[t.y][t.x] == '\\' || t.xD == -1 && rails[t.y][t.x] == '\\' + || t.yD == 1 && rails[t.y][t.x] == '/' || t.yD == -1 && rails[t.y][t.x] == '/' ) { + t.xD = -t.yD + t.yD = oXD + } + } + } + } +} + +export async function taskTwo(input: string[]): Promise { + interface Train { + x: number, y: number, xD: number, yD: number, turnState: number + } + const rails = input.map(i => i.split('')) + let trains: Train[] = [] + for (let y = 0; y < rails.length; y++) { + for (let x = 0; x < rails[y].length; x++) { + const t = rails[y][x] + if (['>', '<', '^', 'v'].includes(t)) { + if (rails[y][x-1] != ' ' && rails[y][x+1] != ' ') { + rails[y][x] = '-' + } else if (rails[y-1][x] != ' ' && rails[y+1][x] != ' ') { + rails[y][x] = '|' + } else { + throw x + ' | ' + y + } + const xD = t == '>' ? 1 : (t == '<' ? -1 : 0) + const yD = t == 'v' ? 1 : (t == '^' ? -1 : 0) + trains.push({x,y,xD,yD, turnState: 0}) + } + } + } + const posSet = new Set() + function addPos(x: number, y: number) { + posSet.add(x+'|'+y) + } + function delPos(x: number, y: number) { + posSet.delete(x+'|'+y) + }function hasPos(x: number, y: number) { + return posSet.has(x+'|'+y) + } + + let toRemove = [] as number[] + while (trains.length > 1) { + trains = trains.sort((a,b) => { + if (a.y == b.y) { + return a.x < b.x ? -1:1 + } + return a.y < b.y ? -1:1 + }) + for (let i = 0; i < trains.length; i++) { + if (toRemove.includes(i)) continue + const t = trains[i] + delPos(t.x,t.y) + t.x += t.xD + t.y += t.yD + if (hasPos(t.x,t.y)) { + toRemove.push(i) + for (let j = 0; j < trains.length; j++) { + if (i == j) continue + if (trains[j].x == t.x && trains[j].y == t.y) { + delPos(trains[j].x, trains[j].y) + toRemove.push(j) + } + } + continue + } + addPos(t.x,t.y) + if (rails[t.y][t.x] == '+') { + const oXD = t.xD + switch(t.turnState) { + case 0: + t.xD = t.yD + t.yD = -oXD + break + case 2: + t.xD = -t.yD + t.yD = oXD + break + case 1: + default: + break + } + t.turnState = (t.turnState + 1) % 3 + } else if (rails[t.y][t.x] != '-' && rails[t.y][t.x] != '|') { + const oXD = t.xD + if (t.xD == 1 && rails[t.y][t.x] == '/' || t.xD == -1 && rails[t.y][t.x] == '/' + || t.yD == 1 && rails[t.y][t.x] == '\\' || t.yD == -1 && rails[t.y][t.x] == '\\' ) { + t.xD = t.yD + t.yD = -oXD + } else if (t.xD == 1 && rails[t.y][t.x] == '\\' || t.xD == -1 && rails[t.y][t.x] == '\\' + || t.yD == 1 && rails[t.y][t.x] == '/' || t.yD == -1 && rails[t.y][t.x] == '/' ) { + t.xD = -t.yD + t.yD = oXD + } + } + } + trains = trains.filter((_,i)=>!toRemove.includes(i)) + toRemove = [] + } + console.log(trains[0].x+','+trains[0].y) +} \ No newline at end of file