From 6d12e6fdebdead8c5662242122861c609d8a6f97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20M=C3=A5rdbrink?= Date: Mon, 8 Dec 2025 20:57:00 +0100 Subject: [PATCH] Day 8 --- d08/main.odin | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 d08/main.odin diff --git a/d08/main.odin b/d08/main.odin new file mode 100644 index 0000000..add23fa --- /dev/null +++ b/d08/main.odin @@ -0,0 +1,122 @@ +package main + +import "core:fmt" +import "core:math" +import "core:slice" +import "core:strconv" +import "core:strings" +import "core:time" + +Vec3 :: [3]int +Edge :: struct { + a, b: Vec3, + dist: f64, +} + +distance :: proc(a, b: Vec3) -> f64 { + dx, dy, dz := f64(b.x - a.x), f64(b.y - a.y), f64(b.z - a.z) + return math.sqrt(dx * dx + dy * dy + dz * dz) +} + +find_circuit :: proc(circuits: ^[dynamic][dynamic]Vec3, pos: Vec3) -> int { + for circuit, idx in circuits { + if slice.contains(circuit[:], pos) do return idx + } + return -1 +} + +same_circuit :: proc(circuits: ^[dynamic][dynamic]Vec3, a, b: Vec3) -> bool { + return find_circuit(circuits, a) == find_circuit(circuits, b) +} + +parse :: proc(line: string) -> Vec3 { + parts := strings.split(line, ",") + x, _ := strconv.parse_int(parts[0]) + y, _ := strconv.parse_int(parts[1]) + z, _ := strconv.parse_int(parts[2]) + return Vec3{x, y, z} +} + +make_edges :: proc(positions: []Vec3) -> [dynamic]Edge { + edges := make([dynamic]Edge) + for i in 0 ..< len(positions) { + for j in i + 1 ..< len(positions) { + append(&edges, Edge{positions[i], positions[j], distance(positions[i], positions[j])}) + } + } + slice.sort_by(edges[:], proc(e1, e2: Edge) -> bool {return e1.dist < e2.dist}) + return edges +} + +merge_circuits :: proc(circuits: ^[dynamic][dynamic]Vec3, a, b: Vec3) { + idx_a := find_circuit(circuits, a) + idx_b := find_circuit(circuits, b) + append(&circuits[idx_a], ..circuits[idx_b][:]) + ordered_remove(circuits, idx_b) +} + +part_1 :: proc(lines: []string) { + positions := slice.mapper(lines, parse) + circuits := make([dynamic][dynamic]Vec3) + for pos in positions { + c := make([dynamic]Vec3) + append(&c, pos) + append(&circuits, c) + } + edges := make_edges(positions) + + for edge, idx in edges { + if idx >= 1000 do break + if same_circuit(&circuits, edge.a, edge.b) do continue + merge_circuits(&circuits, edge.a, edge.b) + } + + sizes := slice.mapper(circuits[:], proc(c: [dynamic]Vec3) -> int {return len(c)}) + slice.reverse_sort(sizes) + result := slice.reduce(sizes[:3], 1, proc(acc, x: int) -> int {return acc * x}) + fmt.printfln(" [Result] %v", result) +} + +part_2 :: proc(lines: []string) { + result := 0 + + positions := slice.mapper(lines, parse) + circuits := make([dynamic][dynamic]Vec3) + for pos in positions { + c := make([dynamic]Vec3) + append(&c, pos) + append(&circuits, c) + } + edges := make_edges(positions) + + for edge in edges { + if same_circuit(&circuits, edge.a, edge.b) do continue + if len(circuits) == 2 { + result = edge.a.x * edge.b.x + break + } + merge_circuits(&circuits, edge.a, edge.b) + } + + fmt.printfln(" [Result] %v", result) +} + +main :: proc() { + context.allocator = context.temp_allocator + defer free_all(context.temp_allocator) + + INPUT :: #load("input.txt", string) + lines := strings.split_lines(strings.trim_space(INPUT)) + + fmt.println("[Part 1]") + start := time.tick_now() + part_1(lines) + duration := time.tick_diff(start, time.tick_now()) + fmt.printfln(" [Time] %vms\n", time.duration_milliseconds(duration)) + + fmt.printfln("[Part 2]") + start = time.tick_now() + part_2(lines) + duration = time.tick_diff(start, time.tick_now()) + fmt.printfln(" [Time] %vms", time.duration_milliseconds(duration)) +}