package main import "core:log" import "core:os" import "core:strconv" import "core:strings" Input :: struct { reports: [dynamic][dynamic]int, } Result1 :: distinct int Result2 :: distinct 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) input.reports = make([dynamic][dynamic]int, 0, 10) string_data := string(raw_data) for line in strings.split_lines_iterator(&string_data) { line_slice := line[:] values := make([dynamic]int) for value in strings.split_by_byte_iterator(&line_slice, ' ') { num := strconv.atoi(value) append(&values, num) } append(&input.reports, values) } return input } free_input :: proc(input: ^Input) { for i in 0 ..< len(input.reports) { delete(input.reports[i]) } delete(input.reports) } // --- Input --- // // --- Helpers --- // check_levels :: proc(report: []int) -> bool { desc := report[0] > report[1] for i in 0 ..< len(report) - 1 { a := report[i] b := report[i + 1] dist := abs(a - b) if (dist < 1 || dist > 3) || (desc && a < b) || (!desc && a > b) { return false } } return true } filter_on_index :: proc(report: []int, index: int) -> [dynamic]int { result := make([dynamic]int) for i in 0 ..< len(report) { if i != index { append(&result, report[i]) } } return result } // --- Helpers --- // // --- Task 1 --- // run_task1 :: proc(input: ^Input, debug: bool) -> Result1 { result: Result1 if debug { print_input(input) } for report in input.reports { if check_levels(report[:]) { result += 1 } } return result } print_result1 :: proc(result: ^Result1) { log.infof("Task 1: %d", result^) } // --- Task 1 --- // // --- Task 2 --- // run_task2 :: proc(input: ^Input, debug: bool) -> Result2 { result: Result2 if debug { print_input(input) } for report in input.reports { safe := check_levels(report[:]) if !safe { log.debugf("Not safe, analyzing: %v", report) for i in 0 ..< len(report) { filtered := filter_on_index(report[:], i) defer delete(filtered) if check_levels(filtered[:]) { log.debugf("Found safe by removing %d at %d", report[i], i) safe = true break } } } if safe { result += 1 } } return result } print_result2 :: proc(result: ^Result2) { log.infof("Task 2: %d", result^) } // --- Task 2 --- //