summary refs log tree commit diff
path: root/04/src/main.rs
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2021-12-03 21:27:38 -0800
committerIrene Knapp <ireneista@gmail.com>2021-12-03 21:27:38 -0800
commit4fbf2687ff604c6dcddfde908e74a434acea7914 (patch)
tree7f9351f4e594f1d69f61fabcf17cd601719bf335 /04/src/main.rs
parent354682636ef508a8d679a0e30711d6b4d464385b (diff)
04 :)
Diffstat (limited to '04/src/main.rs')
-rw-r--r--04/src/main.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/04/src/main.rs b/04/src/main.rs
new file mode 100644
index 0000000..1d47322
--- /dev/null
+++ b/04/src/main.rs
@@ -0,0 +1,136 @@
+use advent_lib::prelude::*;
+
+
+fn main() -> Result<()> {
+  let mut args = std::env::args();
+  if args.len() != 2 {
+    eprintln!("Usage: advent input");
+  }
+  let _ = args.next();
+  let filename = args.next().unwrap();
+
+  let input = advent_lib::group_lines_by_blanks(
+    advent_lib::read_lines_file(&filename)?);
+
+  let mut numbers_called = Vec::new();
+  for word in input[0][0].split(',') {
+    numbers_called.push(word.parse::<i64>()?);
+  }
+
+  let mut boards = Vec::new();
+  for board_lines in &input[1..] {
+    let mut board = Vec::new();
+    for line in board_lines {
+      let mut board_row = Vec::new();
+      for word in line.split_whitespace() {
+        board_row.push(word.parse::<i64>()?);
+      }
+      board.push(board_row);
+    }
+    boards.push(board);
+  }
+
+  {
+    let mut final_score: Option<i64> = None;
+    for i in 0 .. numbers_called.len() {
+      let winning_numbers = &numbers_called[0 .. i];
+      for board in &boards {
+        if is_winner(&board, &winning_numbers) {
+          final_score = Some(score(&board, &winning_numbers));
+          break;
+        }
+      }
+
+      match final_score {
+        Some(_) => { break; }
+        _ => { }
+      }
+    }
+
+    println!("{}", final_score.unwrap());
+  }
+
+  {
+    let mut final_score: Option<i64> = None;
+    for i in 0 .. numbers_called.len() {
+      let mut n_winners = 0;
+      let mut last_non_winner = None;
+
+      let winning_numbers = &numbers_called[0 .. i];
+      for board in &boards {
+        if is_winner(&board, &winning_numbers) {
+          n_winners += 1;
+        } else {
+          last_non_winner = Some(board);
+        }
+      }
+
+      if n_winners == boards.len() - 1 {
+        let final_board = last_non_winner.unwrap();
+        for j in i .. numbers_called.len() {
+          let winning_numbers = &numbers_called[0 .. j];
+          if is_winner(final_board, &winning_numbers) {
+            final_score = Some(score(final_board, &winning_numbers));
+            break;
+          }
+        }
+        break;
+      }
+    }
+
+    println!("{}", final_score.unwrap());
+  }
+
+  Ok(())
+}
+
+
+fn is_winner(board: &Vec<Vec<i64>>, winning_numbers: &[i64]) -> bool {
+  for y in 0 .. 5 {
+    let mut n_winners = 0;
+    for x in 0 .. 5 {
+      if winning_numbers.contains(&board[y][x]) {
+        n_winners += 1;
+      } else {
+        break;
+      }
+    }
+
+    if n_winners == 5 {
+      return true;
+    }
+  }
+
+  for x in 0 .. 5 {
+    let mut n_winners = 0;
+    for y in 0 .. 5 {
+      if winning_numbers.contains(&board[y][x]) {
+        n_winners += 1;
+      } else {
+        break;
+      }
+    }
+
+    if n_winners == 5 {
+      return true;
+    }
+  }
+
+  return false;
+}
+
+
+fn score(board: &Vec<Vec<i64>>, winning_numbers: &[i64]) -> i64 {
+  let mut sum = 0;
+
+  for x in 0 .. 5 {
+    for y in 0 .. 5 {
+      if !winning_numbers.contains(&board[y][x]) {
+        sum += board[y][x];
+      }
+    }
+  }
+
+  return sum * winning_numbers[winning_numbers.len() - 1];
+}
+