package main import "core:container/queue" import "core:fmt" import "core:math" import "core:math/linalg" import "core:os" import "core:slice" import "core:strconv" import "core:strings" import "core:time" import "core:unicode/utf8" import util "../util" trim_and_filter :: proc(items: []string) -> []string { result := make([dynamic]string) for item in items { trimmed := strings.trim_space(item) if trimmed != "" do append(&result, trimmed) } return result[:] } execute_operator :: proc(op: string, a, b: i64) -> i64 { switch op { case "+": return a + b case "*": return a * b } panic("Invalid operator") } part_1 :: proc(lines: []string) { result: i64 = 0 operands_line := lines[len(lines) - 1] operands_raw := strings.split(operands_line, " ") operands := trim_and_filter(operands_raw) accs := make([]i64, len(operands)) for op, idx in operands do if op == "*" do accs[idx] = 1 #reverse for line in lines[:len(lines) - 1] { numbers_raw := strings.split(line, " ") numbers := trim_and_filter(numbers_raw) for number, idx in numbers { num, _ := strconv.parse_i64(number) accs[idx] = execute_operator(operands[idx], accs[idx], num) } } result = math.sum(accs) fmt.printfln(" [Result] %v", result) } part_2 :: proc(lines: []string) { result: i64 = 0 operands_line := lines[len(lines) - 1] operands_raw := strings.split(operands_line, " ") operands := trim_and_filter(operands_raw) num_lines := lines[:len(lines) - 1] max_len := 0 for line in num_lines { if len(line) > max_len do max_len = len(line) } transposed := make([dynamic]string) for char_pos := 0; char_pos < max_len; char_pos += 1 { sb := strings.builder_make() for line in num_lines { if char_pos < len(line) { strings.write_byte(&sb, line[char_pos]) } else { strings.write_byte(&sb, ' ') } } append(&transposed, strings.to_string(sb)) strings.builder_destroy(&sb) } groups := make([dynamic][dynamic]string) current_group := make([dynamic]string) for vertical_str in transposed { if strings.trim_space(vertical_str) == "" { if len(current_group) > 0 { append(&groups, current_group) current_group = make([dynamic]string) } } else { append(¤t_group, vertical_str) } } if len(current_group) > 0 { append(&groups, current_group) } op_idx := 0 for group in groups { acc: i64 = 0 if operands[op_idx] == "*" do acc = 1 for vertical_str in group { num, _ := strconv.parse_i64(strings.trim_space(vertical_str)) acc = execute_operator(operands[op_idx], acc, num) } result += acc op_idx += 1 } fmt.printfln(" [Result] %v", result) } main :: proc() { context.allocator = context.temp_allocator defer free_all(context.temp_allocator) INPUT :: #load("input.txt", string) lines := strings.split(INPUT, "\n") lines = lines[:len(lines) - 1] fmt.println("[Part 1]") start := time.tick_now() part_1(lines) duration := time.tick_diff(start, time.tick_now()) fmt.printfln(" [Time] %vms\n", time.duration_milliseconds(duration)) fmt.printfln("[Part 2]") start = time.tick_now() part_2(lines) duration = time.tick_diff(start, time.tick_now()) fmt.printfln(" [Time] %vms", time.duration_milliseconds(duration)) }