Guest User

aoc04

a guest
Dec 4th, 2021
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.76 KB | None | 0 0
  1. use std::fs::File;
  2. use std::io::{self, BufRead};
  3. use std::path::Path;
  4.  
  5. #[derive(Debug)]
  6. pub struct BingoCell {
  7.     pub selected: bool,
  8.     pub number: u32,
  9. }
  10.  
  11. #[derive(Debug)]
  12. pub struct BingoBoard {
  13.     pub grid: Vec<Vec<BingoCell>>,
  14. }
  15.  
  16. impl BingoBoard {
  17.     /// Tick the number in a grid.
  18.     ///
  19.     /// # Arguments
  20.     ///
  21.     /// * `number` - The number that just been announced.
  22.     pub fn tick_number(&mut self, number: u32) -> bool {
  23.         for row in self.grid.iter_mut() {
  24.             for cell in row.iter_mut() {
  25.                 if cell.number == number && !cell.selected {
  26.                     cell.selected = true;
  27.                     // Each number in a bingo grid are unique...
  28.                     return true;
  29.                 }
  30.             }
  31.         }
  32.         false
  33.     }
  34.  
  35.     /// Test if the grid is a winning one or not.
  36.     ///
  37.     /// # Arguments
  38.     pub fn is_winner(&self) -> bool {
  39.         // Avoid a crash
  40.         if self.grid.is_empty() {
  41.             return false;
  42.         }
  43.  
  44.         // We do both per row and per column at the same time...
  45.         let column_len: usize = self.grid[0].len();
  46.         let mut column_count: Vec<usize> = vec![0; column_len];
  47.         let mut row_count: usize;
  48.  
  49.         for row in self.grid.iter() {
  50.             row_count = 0;
  51.             for (i, cell) in row.iter().enumerate() {
  52.                 if cell.selected {
  53.                     row_count += 1;
  54.                     column_count[i] += 1;
  55.  
  56.                     if column_count[i] == column_len || row_count == row.len() {
  57.                         return true;
  58.                     }
  59.                 }
  60.             }
  61.         }
  62.  
  63.         false
  64.     }
  65.  
  66.     /// Get the final board value (sum of cells "non-selected".
  67.     ///
  68.     /// # Arguments
  69.     pub fn board_value(&self) -> u32 {
  70.         self.grid.iter().map(|row| {
  71.             row.iter().filter_map(|cell| {
  72.                 match cell.selected {
  73.                     true => None,
  74.                     false => Some(cell.number)
  75.                 }
  76.             }).sum::<u32>()
  77.         }).sum::<u32>()
  78.     }
  79. }
  80.  
  81. fn aoc04_part1(draw: &Vec<u32>, boards: &mut Vec<BingoBoard>) -> u32 {
  82.     for number in draw {
  83.         // Adding the number to each board
  84.         for board in boards.iter_mut() {
  85.             if board.tick_number(*number) && board.is_winner() {
  86.                 return number * board.board_value();
  87.             }
  88.         }
  89.     }
  90.     0
  91. }
  92.  
  93. fn aoc04_part2(draw: &Vec<u32>, boards: &mut Vec<BingoBoard>) -> u32 {
  94.     for number in draw {
  95.         // Adding the number to each board
  96.         boards.iter_mut().for_each(|board| { board.tick_number(*number); });
  97.  
  98.         if boards.len() == 1 && boards[0].is_winner() {
  99.             return number * boards[0].board_value();
  100.         }
  101.  
  102.         // THE RETAINNNNNN
  103.         boards.retain(|c| !c.is_winner());
  104.     }
  105.     0
  106. }
  107.  
  108. fn main() {
  109.     let mut draw: Vec<u32> = Vec::new();
  110.     let mut boards: Vec<BingoBoard> = Vec::new();
  111.     let mut reset: bool = false;
  112.     let mut grid: Vec<Vec<BingoCell>> = Vec::new();
  113.  
  114.     if let Ok(lines) = read_lines("./input.txt") {
  115.         // Consumes the iterator, returns an (Optional) String
  116.         for line in lines.into_iter().flatten() {
  117.             // First line is the draw numbers...
  118.             if draw.len() == 0 && !line.is_empty() {
  119.                 draw = line.split(',').filter_map(|c| c.parse::<u32>().ok()).collect::<Vec<u32>>()
  120.             }
  121.             // Others are the bingo grids...
  122.             if reset {
  123.                 if !grid.is_empty() {
  124.                     boards.push(BingoBoard { grid });
  125.                 }
  126.                 grid = Vec::new();
  127.                 reset = false;
  128.             }
  129.             if line.is_empty() {
  130.                 reset = true;
  131.             } else {
  132.                 let cells: Vec<BingoCell> = line.split(' ').filter_map(|c| c.parse::<u32>().ok()).map(|number| BingoCell {
  133.                     selected: false,
  134.                     number
  135.                 }).collect::<Vec<BingoCell>>();
  136.                 if !cells.is_empty() {
  137.                     grid.push(cells);
  138.                 }
  139.             }
  140.         }
  141.     }
  142.  
  143.     // Pushing the last one if any
  144.     if !grid.is_empty() {
  145.         boards.push(BingoBoard {
  146.             grid
  147.         });
  148.     }
  149.  
  150.  
  151.     let result = aoc04_part1(&draw, &mut boards);
  152.     println!("Winner {}", result);
  153.  
  154.     let result = aoc04_part2(&draw, &mut boards);
  155.     println!("Last Winner {}", result);
  156. }
  157.  
  158. // The output is wrapped in a Result to allow matching on errors
  159. // Returns an Iterator to the Reader of the lines of the file.
  160. fn read_lines<P>(filename: P) -> io::Result<io::Lines<io::BufReader<File>>> where P: AsRef<Path>, {
  161.     let file = File::open(filename)?;
  162.     Ok(io::BufReader::new(file).lines())
  163. }
  164.  
Add Comment
Please, Sign In to add comment