Files
advent_of_code/2024/2/odin/main.odin
2025-08-14 10:09:57 +02:00

88 lines
1.9 KiB
Odin

package aoc2024day2
import "core:fmt"
import "core:math"
import "core:os"
import "core:strconv"
import "core:strings"
EXAMPLE_INPUT_PATH :: "example.txt"
PUZZLE_INPUT_PATH :: "input.txt"
main :: proc() {
path := len(os.args) == 2 ? os.args[1] : EXAMPLE_INPUT_PATH
data := os.read_entire_file(path) or_else panic(fmt.tprintf("failed to read", path))
defer delete(data)
numbers: [dynamic]int
defer delete(numbers)
counter1 := 0
counter2 := 0
it := string(data)
for line in strings.split_lines_iterator(&it) {
for word in strings.split(line, " ") {
number := strconv.parse_int(word) or_else panic(fmt.tprintf("failed to parse", word))
append(&numbers, number)
}
diffs := diff(&numbers)
counter1 += int(safe(&diffs))
// or-reduction on safe of each tolerated diff
b := false
for &combination in tolerate(&numbers) {
diffs := diff(&combination)
if safe(&diffs) {
b = true
break
}
}
counter2 += int(b)
clear(&numbers)
}
fmt.println("part 1: there were", counter1, "safe reports.")
fmt.println("part 2: there were", counter2, "safe reports.")
}
diff :: proc(nums: ^[dynamic]int) -> [dynamic]int {
out: [dynamic]int
for cur, i in nums {
if len(nums) - 1 == i {break}
next := nums[i + 1]
append(&out, next - cur)
}
return out
}
safe :: proc(diffs: ^[dynamic]int) -> bool {
for cur, i in diffs {
// not on last element of list ? ... : default
next := len(diffs) - 1 != i ? diffs[i + 1] : cur
// not (same sign and greater than zero && at most 3)
if !(cur * next > 0 && cur * cur <= 9) {
return false
}
}
// fmt.println(safe ? "safe" : "unsafe")
return true
}
tolerate :: proc(diffs: ^[dynamic]int) -> [dynamic][dynamic]int {
out: [dynamic][dynamic]int
for d, i in diffs {
new: [dynamic]int
append(&out, new)
}
for d, i in diffs {
start: []int = diffs^[0:i]
end: []int = diffs^[i + 1:len(diffs)]
append(&out[i], ..start)
append(&out[i], ..end)
}
return out
}