package main
import "core:bytes"
import "core:fmt"
import "core:io"
import "core:os"
import "core:strconv"
import "core:strings"
Card :: struct {
winners: []int,
numbers: []int,
}
Input :: struct {
cards: [dynamic]Card,
}
Result1 :: distinct int
Result2 :: distinct int
// --- Input --- //
print_input :: proc(input: ^Input) {
for card, i in input.cards {
fmt.printf("Card % 3d: ", i + 1)
for n in card.winners {
fmt.printf("% 3d ", n)
}
fmt.printf(" |")
for n in card.numbers {
fmt.printf("% 3d ", n)
}
fmt.printf("\n")
}
}
parse_numbers :: proc(numbers: string) -> []int {
split_numbers := strings.fields(numbers)
result := make([]int, len(split_numbers))
for n, i in split_numbers {
result[i] = strconv.atoi(n)
}
return result
}
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.cards = make([dynamic]Card, 0, 10)
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]
card: Card
start := strings.index(line, ":")
data := strings.split(line[start + 2:], " | ")
card.winners = parse_numbers(data[0])
card.numbers = parse_numbers(data[1])
append(&input.cards, card)
}
return input
}
free_input :: proc(input: ^Input) {
for card in input.cards {
delete(card.winners)
delete(card.numbers)
}
delete(input.cards)
}
// --- Input --- //
// --- Task 1 --- //
run_task1 :: proc(input: ^Input, debug: bool) -> Result1 {
result: Result1
if debug {
print_input(input)
}
for card in input.cards {
count: int
for n in card.numbers {
for w in card.winners {
if n == w {
count = count * 2 if count > 0 else 1
break
}
}
}
result += Result1(count)
}
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)
}
won_cards := make([]int, len(input.cards))
defer delete(won_cards)
for _, i in won_cards {
won_cards[i] = 1
}
for card, i in input.cards {
count: int
for n in card.numbers {
for w in card.winners {
if n == w {
count += 1
break
}
}
}
if count > 0 {
for j := i + 1; j <= i + count && j < len(input.cards); j += 1 {
won_cards[j] += won_cards[i]
}
}
}
for w in won_cards {
result += Result2(w)
}
return result
}
print_result2 :: proc(result: ^Result2) {
fmt.printf("Task 2: %d\n", result^)
}
// --- Task 2 --- //