aoc25/d04/main.odin
2025-12-04 21:33:18 +01:00

118 lines
2.7 KiB
Odin

package main
import "core:container/queue"
import "core:fmt"
import "core:math"
import "core:os"
import "core:slice"
import "core:strconv"
import "core:strings"
import "core:time"
import "core:unicode/utf8"
import util "../util"
Vec2 :: [2]int
in_bounds :: proc(pos: Vec2, lines: ^[][]u8) -> bool {
return pos.x >= 0 && pos.x < len(lines[0]) && pos.y >= 0 && pos.y < len(lines)
}
part_1 :: proc(lines: ^[][]u8) {
result: i64 = 0
directions := [8]Vec2{{0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}}
for line, y in lines {
for ch, x in line {
if ch != '@' do continue
adj_paperroll := 0
pos := Vec2{x, y}
for dir in directions {
adj_pos := pos + dir
if in_bounds(adj_pos, lines) {
adj_ch := lines[adj_pos.y][adj_pos.x]
if adj_ch == '@' do adj_paperroll += 1
}
}
if adj_paperroll < 4 do result += 1
}
}
fmt.printfln(" [Result] %v", result)
}
count_rolls :: proc(lines: ^[][]u8) -> (acc: int) {
for line in lines {
for ch in line do if ch == '@' do acc += 1
}
return
}
part_2 :: proc(lines: ^[][]u8) {
result := 0
directions := [8]Vec2{{0, -1}, {1, -1}, {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}}
to_remove := make([dynamic]Vec2)
mutable_lines := make([][]u8, len(lines))
for line, i in lines {
mutable_lines[i] = slice.clone(line)
}
rolls := count_rolls(&mutable_lines)
for true {
for line, y in mutable_lines {
for ch, x in line {
if ch != '@' do continue
adj_paperroll := 0
pos := Vec2{x, y}
for dir in directions {
adj_pos := pos + dir
if in_bounds(adj_pos, &mutable_lines) {
adj_ch := mutable_lines[adj_pos.y][adj_pos.x]
if adj_ch == '@' do adj_paperroll += 1
}
}
if adj_paperroll < 4 do append(&to_remove, pos)
}
}
for pos in to_remove do mutable_lines[pos.y][pos.x] = '.'
result += len(to_remove)
clear(&to_remove)
new_rolls := count_rolls(&mutable_lines)
if new_rolls == rolls do break
else do rolls = new_rolls
}
fmt.printfln(" [Result] %v", result)
}
main :: proc() {
context.allocator = context.temp_allocator
defer free_all(context.temp_allocator)
INPUT :: #load("input.txt")
lines := strings.split_lines(string(INPUT))
lines = lines[:len(lines) - 1]
byte_lines := make([][]u8, len(lines))
for line, i in lines do byte_lines[i] = transmute([]u8)line
fmt.println("[Part 1]")
start := time.tick_now()
part_1(&byte_lines)
duration := time.tick_diff(start, time.tick_now())
fmt.printfln(" [Time] %fms\n", time.duration_milliseconds(duration))
fmt.printfln("[Part 2]")
start = time.tick_now()
part_2(&byte_lines)
duration = time.tick_diff(start, time.tick_now())
fmt.printfln(" [Time] %fms", time.duration_milliseconds(duration))
}