summaryrefslogtreecommitdiff
path: root/04/src/part-2.rs
diff options
context:
space:
mode:
Diffstat (limited to '04/src/part-2.rs')
-rw-r--r--04/src/part-2.rs95
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));
+ }
+ }
+ }
+}