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) }