advent of code 2025 in ts and nix
at main 4.0 kB view raw
1const file = await Bun.file("../../shared/09/input.txt").text(); 2 3interface Point { 4 x: number; 5 y: number; 6} 7 8// Parse tile coordinates 9const tiles: Point[] = file 10 .trim() 11 .split("\n") 12 .map((line) => { 13 const [x, y] = line.split(",").map(Number); 14 return { x, y }; 15 }); 16 17// Part 1: Any rectangle with red corners 18function part1(points: Point[]): number { 19 let largestRectangleSize = 0; 20 for (let pointAIndex = 0; pointAIndex < points.length; pointAIndex++) { 21 const pointA = points[pointAIndex]; 22 for ( 23 let pointBIndex = pointAIndex + 1; 24 pointBIndex < points.length; 25 pointBIndex++ 26 ) { 27 const pointB = points[pointBIndex]; 28 const rectangleSize = 29 (Math.abs(pointB.x - pointA.x) + 1) * 30 (Math.abs(pointB.y - pointA.y) + 1); 31 if (rectangleSize > largestRectangleSize) { 32 largestRectangleSize = rectangleSize; 33 } 34 } 35 } 36 return largestRectangleSize; 37} 38 39// Part 2: Rectangle must only contain red or green tiles 40function part2(_points: Point[]): number { 41 const minX = Math.min(..._points.map((p) => p.x)) - 1; 42 const minY = Math.min(..._points.map((p) => p.y)) - 1; 43 const __points = _points.map((p) => ({ x: p.x - minX, y: p.y - minY })); 44 45 const xs = __points 46 .map((p) => p.x) 47 .toSorted((a, b) => a - b) 48 .filter((_, i) => i % 2 === 0); 49 const ys = __points 50 .map((p) => p.y) 51 .toSorted((a, b) => a - b) 52 .filter((_, i) => i % 2 === 0); 53 const points = __points.map((p) => ({ 54 x: 1 + xs.indexOf(p.x) * 2, 55 y: 1 + ys.indexOf(p.y) * 2, 56 })); 57 58 const grid: number[][] = []; 59 const width = Math.max(...points.map((p) => p.x)) + 1; 60 const height = Math.max(...points.map((p) => p.y)) + 1; 61 62 for (let y = 0; y <= height; y++) { 63 grid[y] = []; 64 for (let x = 0; x <= width; x++) { 65 grid[y][x] = 0; 66 } 67 } 68 69 points.forEach((p, pIndex) => { 70 grid[p.y][p.x] = 1; 71 const nextPoint = points[(pIndex + 1) % points.length]; 72 const deltaX = Math.sign(nextPoint.x - p.x); 73 const deltaY = Math.sign(nextPoint.y - p.y); 74 if (deltaX !== 0) { 75 let currentX = p.x + deltaX; 76 while (currentX !== nextPoint.x) { 77 if (grid[p.y][currentX] === 0) { 78 grid[p.y][currentX] = 2; 79 } 80 currentX += deltaX; 81 } 82 } 83 if (deltaY !== 0) { 84 let currentY = p.y + deltaY; 85 while (currentY !== nextPoint.y) { 86 if (grid[currentY][p.x] === 0) { 87 grid[currentY][p.x] = 2; 88 } 89 currentY += deltaY; 90 } 91 } 92 }); 93 94 // Flood fill all cells with -1 that are 0 and connected to the border 95 let open = [{ x: 0, y: 0 }]; 96 const floodFill = (x: number, y: number) => { 97 if (x < 0 || x > width || y < 0 || y > height) { 98 return; 99 } 100 if (grid[y][x] !== 0) { 101 return; 102 } 103 grid[y][x] = -1; 104 const add = (nx: number, ny: number) => { 105 if (nx < 0 || nx > width || ny < 0 || ny > height) { 106 return; 107 } 108 if (grid[ny][nx] !== 0) { 109 return; 110 } 111 open.push({ x: nx, y: ny }); 112 }; 113 add(x + 1, y); 114 add(x - 1, y); 115 add(x, y + 1); 116 add(x, y - 1); 117 }; 118 while (open.length > 0) { 119 const point = open.pop()!; 120 floodFill(point.x, point.y); 121 } 122 123 const hasOnlyValidPoints = (pointA: Point, pointB: Point): boolean => { 124 for ( 125 let y = Math.min(pointA.y, pointB.y); 126 y <= Math.max(pointA.y, pointB.y); 127 y++ 128 ) { 129 for ( 130 let x = Math.min(pointA.x, pointB.x); 131 x <= Math.max(pointA.x, pointB.x); 132 x++ 133 ) { 134 if (grid[y][x] < 0) { 135 return false; 136 } 137 } 138 } 139 return true; 140 }; 141 142 let largestRectangleSize = 0; 143 for (let pointAIndex = 0; pointAIndex < points.length; pointAIndex++) { 144 for ( 145 let pointBIndex = pointAIndex + 1; 146 pointBIndex < points.length; 147 pointBIndex++ 148 ) { 149 const pointA = _points[pointAIndex]; 150 const pointB = _points[pointBIndex]; 151 const rectangleSize = 152 (Math.abs(pointB.x - pointA.x) + 1) * 153 (Math.abs(pointB.y - pointA.y) + 1); 154 if ( 155 rectangleSize > largestRectangleSize && 156 hasOnlyValidPoints(points[pointAIndex], points[pointBIndex]) 157 ) { 158 largestRectangleSize = rectangleSize; 159 } 160 } 161 } 162 return largestRectangleSize; 163} 164 165console.log("part 1:", part1(tiles)); 166console.log("part 2:", part2(tiles));