Day 8
This commit is contained in:
parent
8fb9a3c795
commit
6d12e6fdeb
1 changed files with 122 additions and 0 deletions
122
d08/main.odin
Normal file
122
d08/main.odin
Normal file
|
|
@ -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))
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue