diff options
Diffstat (limited to '04/src/part-2.rs')
-rw-r--r-- | 04/src/part-2.rs | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/04/src/part-2.rs b/04/src/part-2.rs new file mode 100644 index 0000000..9903375 --- /dev/null +++ b/04/src/part-2.rs @@ -0,0 +1,95 @@ +mod tensor; + +use std::io::{BufRead}; +use std::collections::{HashMap, HashSet}; +use std::ops::{IndexMut}; + +pub type Matrix = tensor::Tensor<(bool, u64), 2>; +pub type Index = tensor::Index<2>; + +fn read_board(handle: &mut std::io::StdinLock) -> Option<Matrix> { + let mut lines = handle.lines(); + let first_line = lines.next()?.ok()?; + let mut words = first_line.split_whitespace(); + let mut data: Vec<(bool, u64)> = words.map(|x| (false, x.parse().expect("Malformed input"))).collect(); + let n = data.len(); + for i in 1..n { + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split_whitespace(); + data.extend(words.map(|x| (false, x.parse::<u64>().expect("Malformed input")))); + } + lines.next(); + Some(Matrix::new_from([n, n], data)) +} + +fn is_board_winning(board: & Matrix, pivot: Index) -> bool { + let mut win_row = true; + for j in 0..board.shape()[1] { + if !board[[pivot[0], j]].0 { win_row = false; break; } + } + if win_row { return true; } + let mut win_col = true; + for i in 0..board.shape()[0] { + if !board[[i, pivot[1]]].0 { win_col = false; break; } + } + win_col +} + +fn board_score(board: & Matrix) -> u64 { + board.data().into_iter().filter(|x| !x.0).map(|x| x.1).sum() +} + +pub fn main() { + let mut stdin = std::io::stdin(); + + let numbers: Vec<u64> = { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + let line = lines.next().expect("Malformed input").expect("IO error"); + let mut words = line.split(','); + words.map(|s| s.parse().expect("Malformed input")).collect() + }; + + { + let mut handle = stdin.lock(); + let mut lines = handle.lines(); + lines.next(); + } + let mut handle = stdin.lock(); + + let mut boards: Vec<Matrix> = Vec::new(); + let mut inverse: HashMap<u64, Vec<(usize, Index)>> = HashMap::new(); + + while let Some(mat) = read_board(&mut handle) { + let shape = mat.shape(); + for i in 0..shape[0] { + for j in 0..shape[1] { + let x = mat[[i, j]].1; + if let Some(k) = inverse.get_mut(&x) { + k.push((boards.len(), [i, j])); + } + else { inverse.insert(x, vec![(boards.len(), [i, j])]); } + } + } + boards.push(mat); + } + + //println!("Got {} boards and {} inv maps elements.", boards.len(), inverse.len()); + let mut boards_not_yet_won: HashSet<usize> = HashSet::new(); + boards_not_yet_won.extend(0..boards.len()); + for x in numbers.into_iter() { + for (board_num, idx) in inverse.get(&x).unwrap().into_iter() { + //println!("Marking ({}, {}) on board {}", idx[0], idx[1], board_num); + let board: &mut Matrix = boards.index_mut(*board_num); + board[idx].0 = true; + if is_board_winning(board, *idx) { + boards_not_yet_won.remove(board_num); + if boards_not_yet_won.is_empty() { + println!("{}", board_score(board)*x); + return; + } + //winning_boards.push((*board_num, board_score(board)*x)); + } + } + } +} |