139 lines
3.2 KiB
Odin
139 lines
3.2 KiB
Odin
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))
|
|
}
|