export type Direction = "R" | "L" | "U" | "D"; export type Instruction = { direction: Direction; steps: number; color: number; } export function parseInput(content: string): Instruction[] { const lines = content.split("\n").map(x => x.trim()).filter(x => x.length > 0); return lines.map(line => { const m = /^([RDLU])\s+(\d+)\s+\(#([0-9a-f]+)\)$/.exec(line); if (!m) { throw new Error(`unknown line ${line}`); } return { direction: m[1] as Direction, steps: parseInt(m[2]), color: parseInt(m[3], 16), } }); } export async function readInput(filename: string): Promise { const input = await Deno.readTextFile(filename); return parseInput(input); } /** * Clockwise direction */ const CW = [ "R", "D", "L", "U" ] /** * generate a line of edge * @param insts array of instructions */ export function transformEdgeLine(insts: Instruction[]) { const newInst = []; let nextInstBonus = 1; for (let i = 0; i < insts.length - 1; i++) { const inst = insts[i]; const nextInst = insts[i + 1]; const dir = CW.indexOf(inst.direction); const nextDir = CW.indexOf(nextInst.direction); if (dir === nextDir) { nextInstBonus += inst.steps; } else if ((dir + 2) % CW.length === nextDir) { throw new Error("invalid direction"); } else if ((dir + 1) % CW.length === nextDir) { newInst.push({ direction: inst.direction, steps: inst.steps + nextInstBonus, color: inst.color }); nextInstBonus = 1; } else if ((dir + CW.length - 1) % CW.length === nextDir) { newInst.push({ direction: inst.direction, steps: inst.steps + nextInstBonus - 1, color: inst.color }); nextInstBonus = 0; } else { console.log(`unknown direction ${inst.direction} ${nextInst.direction}`); } } newInst.push({ direction: insts[insts.length - 1].direction, steps: insts[insts.length - 1].steps + nextInstBonus, color: insts[insts.length - 1].color }); return newInst; } export function calcArea(insts: Instruction[]) { let pos = [0, 0]; let area = 0; transformEdgeLine(insts).forEach(inst => { if (inst.direction === "R") { pos = [pos[0] + inst.steps, pos[1]]; area += inst.steps * pos[1]; } if (inst.direction === "L") { pos = [pos[0] - inst.steps, pos[1]]; area -= inst.steps * pos[1]; } if (inst.direction === "U") { pos = [pos[0], pos[1] - inst.steps]; } if (inst.direction === "D") { pos = [pos[0], pos[1] + inst.steps]; } }); return Math.abs(area); }