package main
import "core:bytes"
import "core:fmt"
import "core:io"
import "core:os"
Input :: struct {
width: int,
grid: []rune,
}
Result1 :: distinct int
Result2 :: distinct int
// --- 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)
current: int
line: string
err: io.Error
for ; err != .EOF; line, err = bytes.buffer_read_string(&buf, '\n') {
if line == "" || line == "\n" {
continue
}
line = line[:len(line) - 1]
if input.width == 0 {
input.width = len(line)
input.grid = make([]rune, input.width * input.width)
}
for c in line {
input.grid[current] = c
current += 1
}
}
return input
}
free_input :: proc(input: ^Input) {
delete(input.grid)
}
// --- Input --- //
// --- Task 1 --- //
read_number :: proc(line: []rune) -> (num, steps: int) {
for i := 0; i < len(line); i += 1 {
r := line[i]
if r < '0' || r > '9' {
break
}
num *= 10
num += int(r - '0')
steps += 1
}
return
}
print_input :: proc(input: ^Input) {
for r, i in input.grid {
if i % input.width == 0 {
fmt.printf("\n")
}
fmt.printf("%c", r)
}
fmt.printf("\n")
}
run_task1 :: proc(input: ^Input, debug: bool) -> Result1 {
result: Result1
if debug {
print_input(input)
}
for i := 0; i < len(input.grid); i += 1 {
r := input.grid[i]
if r < '0' || r > '9' {
continue
}
start_i := i
num, steps := read_number(input.grid[i:])
i += steps
x := start_i % input.width
y := start_i / input.width
start_x := x - 1 if x > 1 else 0
start_y := y - 1 if y > 1 else 0
end_x := x + steps if x + steps < input.width - 1 else input.width - 1
end_y := y + 1 if y < input.width - 1 else input.width - 1
if debug {
fmt.printf(
"number: %d (%d x %d -> %d x %d -> %d x %d) -> %d\n",
start_i,
start_x,
start_y,
x,
y,
end_x,
end_y,
num,
)
}
has_part: bool
loop: for yy := start_y; yy <= end_y; yy += 1 {
for xx := start_x; xx <= end_x; xx += 1 {
check := input.grid[(yy * input.width) + xx]
if !has_part {
has_part = (check < '0' || check > '9') && check != '.'
}
if !debug && has_part {
break loop
}
if debug {
fmt.printf("%c", check)
}
}
if debug {
fmt.printf("\n")
}
}
if debug {
fmt.printf("has part: %t\n", has_part)
fmt.printf("\n")
}
if has_part {
result += Result1(num)
}
}
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
if debug {
print_input(input)
}
for i := 0; i < len(input.grid); i += 1 {
r := input.grid[i]
if r != '*' {
continue
}
x := i % input.width
y := i / input.width
start_x := x - 1 if x > 1 else 0
start_y := y - 1 if y > 1 else 0
end_x := x + 1 if x < input.width - 1 else input.width - 1
end_y := y + 1 if y < input.width - 1 else input.width - 1
if debug {
fmt.printf("number: %d (%d x %d -> %d x %d -> %d x %d)\n", i, start_x, start_y, x, y, end_x, end_y)
}
count: int
total := 1
loop: for yy := start_y; yy <= end_y; yy += 1 {
for xx := start_x; xx <= end_x; xx += 1 {
grid_i := (yy * input.width) + xx
check := input.grid[grid_i]
if check >= '0' && check <= '9' {
left := xx
for ; left >= 0; left -= 1 {
check_i := (yy * input.width) + left
if input.grid[check_i] < '0' || input.grid[check_i] > '9' {
break
}
}
left += 1
num, steps := read_number(input.grid[(yy * input.width) + left:])
xx = left + steps
if debug {
fmt.printf("valid: %d\n", num)
}
count += 1
total *= num
}
}
}
if debug {
fmt.printf("ratio: %d, count: %d\n", total, count)
}
if count == 2 {
result += Result2(total)
}
}
return result
}
print_result2 :: proc(result: ^Result2) {
fmt.printf("Task 2: %d\n", result^)
}
// --- Task 2 --- //