#import "Basic";
#import "String";
#import "File";

solve_day3 :: (test: bool) {
    contents := read_entire_file("inputs/day3.txt");
    grid := split(contents, "\n");

    numbers : [..][..]Line_Number;

    for 0..grid.count - 1 {
        dummy: [..]Line_Number;
        array_add(*numbers, dummy);
    }

    line_number: Line_Number;

    part1 := 0;
    part2 := 0;
    has_symbol := false;

    for line, line_index: grid {
        for 0..line.count - 1 {

            if is_digit(line[it]) {
                if line_number.value == -1 {
                    line_number.start = it;
                    line_number.value = 0;
                }
                line_number.value = line_number.value * 10 + (line[it] - #char "0");
                has_symbol = has_symbol || has_symbol_adjacent(it, line_index, grid);

            } 
            if line_number.value != -1 && (!is_digit(line[it]) || it == line.count - 1) {
                line_number.end = it - 1;

                array_add(*numbers[line_index], line_number);

                if has_symbol {
                    part1 += line_number.value;
                    has_symbol = false;
                }

                line_number.value = -1;
            }
        }
    }

    for line, line_index: grid {
        for 0..line.count - 1 {
            number_count := 0;
            product := 1;
            if line[it] == #char "*" {

                for i: int.[-1,0,1] {
                    if line_index + i < 0 || line_index + i >= grid.count  continue;

                    for num: numbers[line_index + i] {
                        if (num.start >= (it - 1) && num.start <= (it + 1)) || (num.end >= (it - 1) && num.end <= (it + 1)) {
                            number_count += 1;
                            product = product * num.value;
                        }
                    }
                }

                if number_count == 2  part2 += product;
            }
        }
    }

    print("Part 1: %\n", part1);
    print("Part 2: %\n", part2);
}

has_symbol_adjacent :: (x: s64, y: s64, grid: []string) -> bool {

    for x_offset: int.[-1,0,1] {
        if x_offset + x < 0 || x_offset + x >= grid[0].count  continue;
        for y_offset: int.[-1,0,1] {
            if y_offset + y < 0 || y_offset + y >= grid[0].count  continue;

            char := grid[y + y_offset][x + x_offset];

            if is_digit(char) || char == #char "."  continue;

            return true;
        }
    }

    return false;
}


Line_Number :: struct {
    value: s64 = -1;
    start: s64;
    end: s64;
}