package day_11
import "core:log"
import "core:os"
import "core:strings"
Input :: struct {
rack_wires: map[string][]string,
}
Result1 :: int
Result2 :: int
// --- Input --- //
print_input :: proc(input: Input) {
log.infof("%v", input)
}
parse_input_file :: proc(filepath: string) -> Input {
input: Input
raw_data, ok := os.read_entire_file_from_filename(filepath)
if !ok {
panic("oh no, could not read file")
}
defer delete(raw_data)
lines, err := strings.split_lines(strings.trim_space(string(raw_data)))
if err != .None {
panic("oh no, failed splitting into lines")
}
defer delete(lines)
input.rack_wires = make(map[string][]string)
for line in lines {
rack_wires := strings.split(line, ":")
defer delete(rack_wires)
wires := strings.split(strings.trim_space(rack_wires[1]), " ")
defer delete(wires)
rack := strings.clone(rack_wires[0])
input.rack_wires[rack] = make([]string, len(wires))
for w, i in wires {
input.rack_wires[rack][i] = strings.clone(strings.trim_space(w))
}
}
return input
}
free_input :: proc(input: ^Input) {
for i in input.rack_wires {
for w in input.rack_wires[i] {
delete(w)
}
delete(i)
delete(input.rack_wires[i])
}
delete(input.rack_wires)
}
// --- Input --- //
// --- Helpers --- //
State :: struct {
node: string,
seen_fft: bool,
seen_dac: bool,
}
paths :: proc(input: Input, paths_cache: ^map[string]int, name: string) -> int {
if name == "out" {
return 1
}
if cached, ok := paths_cache[name]; ok {
return cached
}
total: int
for child in input.rack_wires[name] {
total += paths(input, paths_cache, child)
}
paths_cache[name] = total
return total
}
paths_fft_dac :: proc(
input: Input,
paths_cache: ^map[State]int,
name: string,
seen_fft := false,
seen_dac := false,
) -> int {
if name == "out" {
return 1 if seen_fft && seen_dac else 0
}
state := State {
node = name,
seen_fft = seen_fft,
seen_dac = seen_dac,
}
if cached, ok := paths_cache[state]; ok {
return cached
}
state.seen_fft = seen_fft
state.seen_dac = seen_dac
total: int
for child in input.rack_wires[name] {
total += paths_fft_dac(
input,
paths_cache,
child,
(state.seen_fft || child == "fft"),
(state.seen_dac || child == "dac"),
)
}
paths_cache[state] = total
return total
}
// --- Helpers --- //
// --- Task 1 --- //
run_task1 :: proc(input: Input) -> Result1 {
result: Result1
paths_cache := make(map[string]int)
defer delete(paths_cache)
result = paths(input, &paths_cache, "you")
return result
}
print_result1 :: proc(result: Result1) {
log.infof("Task 1: %d", result)
}
// --- Task 1 --- //
// --- Task 2 --- //
run_task2 :: proc(input: Input) -> Result2 {
result: Result2
paths_cache := make(map[State]int)
defer delete(paths_cache)
result = paths_fft_dac(input, &paths_cache, "svr")
return result
}
print_result2 :: proc(result: Result2) {
log.infof("Task 2: %d", result)
}
// --- Task 2 --- //
run :: proc() {
input := parse_input_file("input/day_11.txt")
defer free_input(&input)
result1 := run_task1(input)
print_result1(result1)
result2 := run_task2(input)
print_result2(result2)
}