121 lines
3.5 KiB
TypeScript
121 lines
3.5 KiB
TypeScript
|
type Direction = "R" | "L" | "U" | "D";
|
||
|
|
||
|
type Instruction = {
|
||
|
direction: Direction;
|
||
|
steps: number;
|
||
|
color: number;
|
||
|
}
|
||
|
|
||
|
async function readInput(filename: string): Promise<Instruction[]> {
|
||
|
const input = await Deno.readTextFile(filename);
|
||
|
const lines = input.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),
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
const input = await readInput("input.txt");
|
||
|
|
||
|
function calcWidthAndHeight(insts: Instruction[]){
|
||
|
let maxX = 0, maxY = 0;
|
||
|
let minX = 0, minY = 0;
|
||
|
insts.reduce<[number,number]>(([x,y]: [number, number], b: Instruction) => {
|
||
|
maxX = Math.max(maxX, x);
|
||
|
maxY = Math.max(maxY, y);
|
||
|
minX = Math.min(minX, x);
|
||
|
minY = Math.min(minY, y);
|
||
|
|
||
|
if (b.direction === "R"){
|
||
|
return [x + b.steps, y];
|
||
|
}
|
||
|
if (b.direction === "L"){
|
||
|
return [x - b.steps, y];
|
||
|
}
|
||
|
if (b.direction === "U"){
|
||
|
return [x, y - b.steps];
|
||
|
}
|
||
|
if (b.direction === "D"){
|
||
|
return [x, y + b.steps];
|
||
|
}
|
||
|
throw new Error(`unknown direction ${b.direction}`);
|
||
|
}, [0,0] as [number, number]);
|
||
|
return {
|
||
|
size: [maxX - minX + 1, maxY - minY + 1],
|
||
|
initPos: [-minX, -minY]
|
||
|
};
|
||
|
}
|
||
|
const {size:[width, height],
|
||
|
initPos: [initX, initY]} = calcWidthAndHeight(input);
|
||
|
|
||
|
console.log((`x: ${width}, y: ${height}`));
|
||
|
|
||
|
function drawMap(instructions: Instruction[], initX: number, initY: number, width: number, height:number){
|
||
|
const map = new Array(height).fill(0).map(()=>new Array(width).fill(".")) as string[][];
|
||
|
let [x, y] = [initX, initY];
|
||
|
instructions.forEach(({direction, steps, color}) => {
|
||
|
for (let i = 0; i < steps; i++) {
|
||
|
if (direction === "R"){
|
||
|
map[y][x] = "#"//rgb24("#", color);
|
||
|
x++;
|
||
|
}
|
||
|
if (direction === "L"){
|
||
|
map[y][x] = "#"//rgb24("#", color);
|
||
|
x--;
|
||
|
}
|
||
|
if (direction === "U"){
|
||
|
map[y][x] = "#"//rgb24("#", color);
|
||
|
y--;
|
||
|
}
|
||
|
if (direction === "D"){
|
||
|
map[y][x] = "#"//rgb24("#", color);
|
||
|
y++;
|
||
|
}
|
||
|
}
|
||
|
});
|
||
|
|
||
|
// fill inner
|
||
|
for (let i = 1; i < height - 1; i++) {
|
||
|
let isInner = false;
|
||
|
let upDetected = false;
|
||
|
let downDetected = false;
|
||
|
let j = 0;
|
||
|
while (j < width - 1) {
|
||
|
if (map[i][j] === "#"){
|
||
|
if (map[i - 1][j] === "#"){
|
||
|
upDetected = !upDetected;
|
||
|
}
|
||
|
if (map[i + 1][j] === "#"){
|
||
|
downDetected = !downDetected;
|
||
|
}
|
||
|
if (upDetected && downDetected){
|
||
|
isInner = true;
|
||
|
}
|
||
|
if (!upDetected && !downDetected){
|
||
|
isInner = false;
|
||
|
}
|
||
|
}
|
||
|
if (isInner && map[i][j] === "."){
|
||
|
map[i][j] = "@";
|
||
|
}
|
||
|
j++;
|
||
|
}
|
||
|
}
|
||
|
// console.log(map.map(x => x.join("")).join("\n"));
|
||
|
return map.map(x => x.join("")).join("\n");
|
||
|
}
|
||
|
|
||
|
const map = drawMap(input, initX, initY, width, height);
|
||
|
await Deno.writeTextFile("output.txt", map);
|
||
|
|
||
|
console.log(map.split("").filter(x => x === "#" || x === "@").length);
|
||
|
|
||
|
|