AOC Day 4 Part Two

mail@pastecode.io avatar
unknown
plain_text
2 years ago
6.9 kB
1
Indexable
Never
use std::io::{self, BufRead};
use std::fs::File;

struct BoardNumber {
    value: u32,
    marked: bool,
}

struct Board {
    value_arr: Vec<Vec<BoardNumber>>,
}

impl Board {
    fn new() -> Board {
        let board = Board {
            value_arr: vec![
                vec![
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                ],
                vec![
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                ],
                vec![
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                ],
                vec![
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                ],
                vec![
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                    BoardNumber { value: 0, marked: false },
                ],
            ]
        };
        return board;
    }

    fn mark_number(&mut self, number: u32) {
        for line in &mut self.value_arr {
            for board_num in line {
                if number == board_num.value {
                    board_num.marked = true;
                }
            }
        }
    }

    fn sum_unmarked(&self) -> u32 {
        let mut sum: u32 = 0;

        for line in &self.value_arr {
            for board_num in line {
                if !board_num.marked { sum += board_num.value }
            }
        }

        sum
    }

    fn check_win(&self) -> bool {
        self.check_horiz() || self.check_vertical() || self.check_diagonal()
    }

    fn print_board(&self) {
        for line in &self.value_arr {
            println!("{} {} {} {} {}", line[0].value, line[1].value, line[2].value, line[3].value, line[4].value)
        }
    }

    fn check_diagonal(&self) -> bool {
        let diagonal_one = self.value_arr[0][0].marked
            && self.value_arr[1][1].marked
            && self.value_arr[2][2].marked
            && self.value_arr[3][3].marked
            && self.value_arr[4][4].marked;

        let diagonal_two = self.value_arr[4][0].marked
            && self.value_arr[3][1].marked
            && self.value_arr[2][2].marked
            && self.value_arr[1][3].marked
            && self.value_arr[0][4].marked;

        diagonal_one || diagonal_two
    }

    fn check_vertical(&self) -> bool {
        for i in 0..5 {
            let v_win = self.value_arr[i][0].marked
                && self.value_arr[i][1].marked
                && self.value_arr[i][2].marked
                && self.value_arr[i][3].marked
                && self.value_arr[i][4].marked;
            if v_win { return true; }
        }
        false
    }

    fn check_horiz(&self) -> bool {
        for i in 0..5 {
            let h_win = self.value_arr[0][i].marked
                && self.value_arr[1][i].marked
                && self.value_arr[2][i].marked
                && self.value_arr[3][i].marked
                && self.value_arr[4][i].marked;
            if h_win { return true; }
        }
        false
    }
}

fn main() {
    //Read in file
    let file = File::open("./input.txt").unwrap();
    let lines = io::BufReader::new(file).lines();

    let mut str_lines: Vec<String> = Vec::new();

    for line in lines {
        if let Ok(input) = line {
            str_lines.push(input);
        }
    }

    //Get numbers
    let mut numbers: Vec<u32> = Vec::new();
    for token in str_lines[0].split(',') {
        numbers.push(token.parse().unwrap());
    }

    //Count boards
    let mut num_boards: usize = 0;
    for line in &str_lines {
        if line.is_empty() { num_boards += 1 }
    }
    num_boards -= 1;

    //Build boards
    let mut boards: Vec<Board> = Vec::new();

    for board_idx in 0..num_boards {
        let mut board = Board::new();
        let mut vec_nums: Vec<Vec<u32>> = Vec::new();

        let start_line: usize = board_idx * 6 + 2;
        let line_width: usize = 5;

        for i in 0..line_width {
            let line = str_lines[start_line + i].clone();
            vec_nums.push(Vec::new());
            for token in line.split_whitespace() {
                vec_nums[i].push(token.parse().unwrap());
            }
        }

        for x in 0..line_width {
            for y in 0..line_width {
                board.value_arr[x][y].value = vec_nums[x][y];
            }
        }

        boards.push(board);
    }

    //Run game
    let mut last_num: u32;
    let mut num_idx: usize = 0;
    let mut last_found = false;

    while !last_found {
        last_num = numbers[num_idx];

        for mut b in &mut boards{
            b.mark_number(last_num);
        }

        let mut count_winning = 0;
        for b in &boards{
            if b.check_win() {count_winning += 1}
        }

        if count_winning == num_boards - 1{
            for mut b in &mut boards{
                if !b.check_win() {
                    //Play until win
                    let mut board_wins = false;
                    while !board_wins {
                        last_num = numbers[num_idx];

                        b.mark_number(last_num);
                        if b.check_win() {
                            let board_sum = b.sum_unmarked();
                            let value = board_sum * last_num;
                            println!("Winning value: {}", value);
                            board_wins = true;
                            last_found = true;
                        }

                        num_idx += 1;
                    }
                }
            }
        }

        num_idx += 1;
    }
}