128 lines
2.9 KiB
Odin
128 lines
2.9 KiB
Odin
package main
|
|
|
|
import "base:intrinsics"
|
|
import "core:fmt"
|
|
import "core:math"
|
|
import "core:slice"
|
|
import "core:strconv"
|
|
import "core:strings"
|
|
import "core:time"
|
|
|
|
Vec3 :: [3]int
|
|
Distance :: struct {
|
|
pos: Vec3,
|
|
distance: int,
|
|
}
|
|
|
|
distance :: proc(a, b: Vec3) -> int {
|
|
dx := f32(b.x - a.x)
|
|
dy := f32(b.y - a.y)
|
|
dz := f32(b.z - a.z)
|
|
|
|
return int(math.sqrt(dx * dx + dy * dy + dz * dz))
|
|
}
|
|
|
|
in_circuit :: proc(circuits: ^[dynamic][dynamic]Vec3, pos: Vec3) -> (circuit: ^[dynamic]Vec3, ok: bool) {
|
|
for &circuit in circuits {
|
|
if slice.contains(circuit[:], pos) do return &circuit, true
|
|
}
|
|
|
|
return {}, false
|
|
}
|
|
|
|
get_min_distance :: proc(
|
|
distance_table: ^[dynamic][dynamic]Distance,
|
|
position: []Vec3,
|
|
) -> (
|
|
p1: Vec3,
|
|
p2: Vec3,
|
|
ok: bool,
|
|
) {
|
|
min := 10000000
|
|
min_idx := 10000000
|
|
for distances, idx in distance_table {
|
|
if len(distances) <= 0 do continue
|
|
if distances[0].distance < min {
|
|
min = distances[0].distance
|
|
min_idx = idx
|
|
p1 = position[idx]
|
|
p2 = distances[0].pos
|
|
ok = true
|
|
}
|
|
}
|
|
|
|
if !ok do return
|
|
|
|
pop(&distance_table[min_idx])
|
|
return
|
|
}
|
|
|
|
part_1 :: proc(lines: []string) {
|
|
result := 1
|
|
positions := slice.mapper(lines, 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}
|
|
})
|
|
|
|
circuits := make([dynamic][dynamic]Vec3)
|
|
distance_table := make([dynamic][dynamic]Distance)
|
|
|
|
for p1, idx1 in positions {
|
|
append(&distance_table, make([dynamic]Distance)) // Without itself
|
|
for p2, idx2 in positions {
|
|
if idx1 == idx2 do continue
|
|
append(&distance_table[idx1], Distance{p2, distance(p1, p2)})
|
|
}
|
|
slice.sort_by(distance_table[idx1][:], proc(dst1, dst2: Distance) -> bool {
|
|
return dst1.distance < dst2.distance
|
|
})
|
|
}
|
|
|
|
for true {
|
|
p1, p2, found := get_min_distance(&distance_table, positions)
|
|
if !found do break
|
|
c, ok := in_circuit(&circuits, p1)
|
|
|
|
if ok do append(c, p2)
|
|
else {
|
|
append(&circuits, make([dynamic]Vec3))
|
|
new_c := &circuits[len(circuits) - 1]
|
|
append(new_c, p1)
|
|
append(new_c, p2)
|
|
}
|
|
}
|
|
for c in circuits do result *= fmt.println(len(c))
|
|
for c in circuits do result *= len(c)
|
|
|
|
fmt.printfln(" [Result] %v", result)
|
|
}
|
|
|
|
part_2 :: proc(lines: []string) {
|
|
result: i64 = 0
|
|
|
|
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(INPUT, "\n")
|
|
lines = lines[:len(lines) - 1]
|
|
|
|
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))
|
|
}
|