Solve 2024-12

Add side-aware coordinate utils
This commit is contained in:
2024-12-12 19:19:44 +01:00
parent 3c9b48b3a6
commit feb1b40408
5 changed files with 266 additions and 3 deletions
+113
View File
@@ -0,0 +1,113 @@
import { sumArray } from '../../utils/array.ts';
import {
calculateSides,
type Coordinates,
getAdjacent,
getNeighbouringSides,
isCoordinateEqual
} from '../../utils/coordinates.ts';
function searchNeighbours(
visited: Set<number>,
rows: string[],
char: string,
x: number,
y: number,
found: Coordinates
) {
const position = y * rows.length + x;
if (visited.has(position)) {
return;
}
visited.add(position);
found.push([x, y]);
const { left, top, right, down } = getAdjacent(rows, x, y);
if (left === char) {
searchNeighbours(visited, rows, char, x - 1, y, found);
}
if (top === char) {
searchNeighbours(visited, rows, char, x, y - 1, found);
}
if (right === char) {
searchNeighbours(visited, rows, char, x + 1, y, found);
}
if (down === char) {
searchNeighbours(visited, rows, char, x, y + 1, found);
}
}
function groupChars(input: string) {
const rows = input.split('\n');
const groups: { char: string; coords: Coordinates }[] = [];
const visited = new Set<number>();
for (let y = 0; y < rows.length; y++) {
for (let x = 0; x < rows[y].length; x++) {
const position = y * rows.length + x;
if (visited.has(position)) {
continue;
}
const char = rows[y][x];
const coords: Coordinates = [];
searchNeighbours(visited, rows, char, x, y, coords);
groups.push({ char, coords });
}
}
return groups;
}
function getPerimeter(g: Coordinates): number {
if (g.length === 1) {
return 4;
}
if (g.length === 2) {
return 6;
}
const { uniqueSides } = calculateSides(g);
return uniqueSides.length;
}
export function solveFirst(input: string): number {
const groups = groupChars(input);
return sumArray(groups.map((g) => g.coords.length * getPerimeter(g.coords)));
}
export function solveSecond(input: string): number {
const groups = groupChars(input);
return sumArray(groups.map((g) => g.coords.length * getSides(g.coords)));
}
export function getSides(g: Coordinates): number {
if (g.length === 1) {
return 4;
}
if (g.length === 2) {
return 4;
}
const { uniqueSides } = calculateSides(g);
const visited = new Set<number>();
let sides = 0;
for (let i = 0; i < uniqueSides.length; i++) {
if (visited.has(i)) {
continue;
}
visited.add(i);
sides++;
const { neighbours } = getNeighbouringSides(uniqueSides[i], uniqueSides);
neighbours.forEach((c) =>
visited.add(uniqueSides.findIndex((v) => isCoordinateEqual(v, c)))
);
}
return sides;
}