Files
code-advent-2025/src/exercises/day_8.ts

181 lines
4.8 KiB
TypeScript

interface Coordinate {
x: number;
y: number;
z: number;
}
export default async function Playground() {
const junction_boxes_coords = await read_junction_box_3d_positions(
"src/exercises/assets/day_8_input.txt",
);
console.log(
">> Three largest pairings mul: ",
get_three_largest_pairings_mul(junction_boxes_coords, 1000),
);
console.log(
">> Last pairing mul: ",
get_last_pairing_mul(junction_boxes_coords),
);
}
export function get_three_largest_pairings_mul(
box_list: Coordinate[],
max_pairings: number,
): number {
const pairing_list = generate_n_shortest_pairings(box_list, max_pairings)
.sort((a, b) => b.length - a.length);
let total = 1;
for (let i = 0; i < 3; i++) {
total *= pairing_list[i].length;
}
return total;
}
export function get_last_pairing_mul(box_list: Coordinate[]): number {
const last_pairing = get_last_pairing_circuit(box_list);
if (last_pairing) {
return box_list[last_pairing.a].x * box_list[last_pairing.b].x;
}
return 0;
}
interface DistancePairing {
a: number;
b: number;
distance: number;
}
function generate_n_shortest_distances(
box_list: Coordinate[],
n: number,
initial_distances?: DistancePairing[],
): DistancePairing[] {
const distances: DistancePairing[] = initial_distances ?? [];
for (let i = 0; i < n; i++) {
const shortest_distance: { distance: number; pair_index: number[] } = {
distance: Infinity, // Dirty, but it's late
pair_index: [],
};
box_list.forEach((box, box_index) => {
for (let next_i = box_index + 1; next_i < box_list.length; next_i++) {
const next_box = box_list[next_i];
const next_distance = calc_distance(box, next_box);
if (
next_distance < shortest_distance.distance &&
!distances.some((d) =>
(d.a === box_index && d.b === next_i) ||
(d.b === box_index && d.a === next_i)
)
) {
shortest_distance.distance = next_distance;
shortest_distance.pair_index = [box_index, next_i];
}
}
});
distances.push({
a: shortest_distance.pair_index[0],
b: shortest_distance.pair_index[1],
distance: shortest_distance.distance,
});
}
return distances;
}
function generate_n_shortest_pairings(
box_list: Coordinate[],
max_pairings: number,
): number[][] {
const distance_list = generate_n_shortest_distances(box_list, max_pairings);
const circuits: number[][] = box_list.map((_, i) => [i]);
distance_list.forEach((distance) => {
const a = circuits.find((c) => c.includes(distance.a));
const b = circuits.find((c) => c.includes(distance.b));
if (a?.length && b?.length && a !== b) {
const to_empty_index = circuits.findIndex((c) => c.includes(distance.b));
b.forEach((x) => a.push(x));
circuits[to_empty_index] = [];
}
});
return circuits;
}
function get_last_pairing_circuit(
box_list: Coordinate[],
): DistancePairing | undefined {
const INCREMENT = 10; // NOTE: to adjust computation cost, since the solution is inefficient
const circuits: number[][] = box_list.map((_, i) => [i]);
const is_done = (c: number[][]): boolean => {
return c.reduce((prev, current) => {
if (current.length > 0) {
return prev + 1;
}
return prev;
}, 0) > 1
? false
: true;
};
let last_pairing: DistancePairing | undefined;
let distance_list = generate_n_shortest_distances(box_list, INCREMENT);
while (!is_done(circuits)) {
distance_list = generate_n_shortest_distances(
box_list,
INCREMENT,
distance_list,
);
distance_list.forEach((distance) => {
const a = circuits.find((c) => c.includes(distance.a));
const b = circuits.find((c) => c.includes(distance.b));
if (a?.length && b?.length && a !== b) {
last_pairing = {
a: distance.a,
b: distance.b,
distance: distance.distance,
};
const to_empty_index = circuits.findIndex((c) =>
c.includes(distance.b)
);
b.forEach((x) => a.push(x));
circuits[to_empty_index] = [];
}
});
}
return last_pairing;
}
function calc_distance(a: Coordinate, b: Coordinate): number {
return Math.sqrt(
Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2) + Math.pow(a.z - b.z, 2),
);
}
export async function read_junction_box_3d_positions(
path: string,
): Promise<Coordinate[]> {
const file_txt = await Deno.readTextFile(path);
const coordinates: Coordinate[] = [];
file_txt.split("\n").forEach((raw_coord) => {
if (!raw_coord.length) {
return;
}
const coord_array = raw_coord.split(",");
coordinates.push({
x: parseInt(coord_array[0]),
y: parseInt(coord_array[1]),
z: parseInt(coord_array[2]),
});
});
return coordinates;
}