package main import "core:bytes" import "core:fmt" import "core:io" import "core:os" import "core:strconv" import "core:strings" Input :: struct { seeds: [dynamic]int, maps: [dynamic][dynamic][3]int, } Result1 :: distinct int Result2 :: distinct int // --- Input --- // print_input :: proc(input: ^Input) { fmt.printf("%#v\n", 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") } buf: bytes.Buffer bytes.buffer_init(&buf, raw_data) defer bytes.buffer_destroy(&buf) input.seeds = make([dynamic]int, 0, 10) input.maps = make([dynamic][dynamic][3]int, 0, 10) line: string line, _ = bytes.buffer_read_string(&buf, '\n') seeds_string := strings.split(line, ": ") defer delete(seeds_string) seeds := strings.fields(seeds_string[1]) defer delete(seeds) for seed in seeds { append(&input.seeds, strconv.atoi(seed)) } bytes.buffer_read_string(&buf, '\n') bytes.buffer_read_string(&buf, '\n') current_map := make([dynamic][3]int, 0, 10) err: io.Error for ;; line, err = bytes.buffer_read_string(&buf, '\n') { if line == "" || line == "\n" { append(&input.maps, current_map) current_map = make([dynamic][3]int, 0, 10) if err == .EOF { break } continue } line = line[:len(line) - 1] if strings.index(line, ":") > -1 { continue } lookup := strings.fields(line) defer delete(lookup) append(¤t_map, [3]int{strconv.atoi(lookup[0]), strconv.atoi(lookup[1]), strconv.atoi(lookup[2])}) } return input } free_input :: proc(input: ^Input) { for m in input.maps { delete(m) } delete(input.maps) delete(input.seeds) } // --- Input --- // // --- Task 1 --- // translate_seed :: proc(m: [][3]int, seed: int, debug: bool = false) -> int { s := seed if debug { fmt.printf("\ttranslating: %d\n", s) } for t in m { dst_a, dst_b := t[0], t[0] + t[2] src_a, src_b := t[1], t[1] + t[2] if seed >= src_a && seed < src_b { s = dst_a + (seed - src_a) if debug { fmt.printf("\t\t%d->%d, %d->%d, %d=%d\n", dst_a, dst_b, src_a, src_b, seed, s) } break } } return s } run_task1 :: proc(input: ^Input, debug: bool) -> Result1 { result: Result1 = -1 if debug { print_input(input) } for seed in input.seeds { s := seed if debug { fmt.printf("seed: %d\n", s) } for m in input.maps { s = translate_seed(m[:], s, debug) } if result == -1 || Result1(s) < result { result = Result1(s) } if debug { fmt.printf("location: %d->%d\n", seed, s) } } return result } print_result1 :: proc(result: ^Result1) { fmt.printf("Task 1: %d\n", result^) } // --- Task 1 --- // // --- Task 2 --- // run_task2 :: proc(input: ^Input, debug: bool) -> Result2 { result: Result2 = -1 if debug { print_input(input) } for i := 0; i < len(input.seeds); i += 2 { start := input.seeds[i] end := start + input.seeds[i + 1] fmt.printf("scanning %d-%d, %d seeds\n", start, end, end - start + 1) for seed in start ..= end { s := seed if debug { fmt.printf("seed: %d\n", s) } for m in input.maps { s = translate_seed(m[:], s, debug) } if result == -1 || Result2(s) < result { result = Result2(s) fmt.printf("New result: seed %d -> location %d\n", seed, s) } if debug { fmt.printf("location: %d->%d\n", seed, s) } } } return result } print_result2 :: proc(result: ^Result2) { fmt.printf("Task 2: %d\n", result^) } // --- Task 2 --- //