119 lines
2.9 KiB
Rust
119 lines
2.9 KiB
Rust
|
use std::error::Error;
|
||
|
use std::fs::File;
|
||
|
use std::io::{self, BufRead};
|
||
|
use std::vec::Vec;
|
||
|
|
||
|
struct Board {
|
||
|
numbers: Vec<Vec<i32>>,
|
||
|
marked: Vec<Vec<bool>>,
|
||
|
}
|
||
|
|
||
|
impl Board {
|
||
|
fn from_lines(lines: &mut impl Iterator<Item = String>) -> Option<Board> {
|
||
|
let mut numbers = Vec::new();
|
||
|
let mut marked = Vec::new();
|
||
|
|
||
|
while let Some(line) = lines.next() {
|
||
|
if line == "" {
|
||
|
break;
|
||
|
}
|
||
|
let row: Vec<i32> = line
|
||
|
.split(" ")
|
||
|
.filter(|n| n.len() != 0)
|
||
|
.map(|n| n.parse().unwrap())
|
||
|
.collect();
|
||
|
let mut markers: Vec<bool> = Vec::new();
|
||
|
markers.resize(row.len(), false);
|
||
|
numbers.push(row);
|
||
|
marked.push(markers);
|
||
|
}
|
||
|
|
||
|
if numbers.len() != 0 {
|
||
|
Some(Board { numbers, marked })
|
||
|
} else {
|
||
|
None
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn mark(&mut self, num: i32) {
|
||
|
for y in 0..self.numbers.len() {
|
||
|
for x in 0..self.numbers[y].len() {
|
||
|
if self.numbers[y][x] == num {
|
||
|
self.marked[y][x] = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn has_won(&self) -> bool {
|
||
|
if self.marked.iter().any(|r| r.iter().all(|m| *m)) {
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
for x in 0..self.marked[0].len() {
|
||
|
let mut col = true;
|
||
|
for y in 0..self.marked.len() {
|
||
|
col = col && self.marked[y][x];
|
||
|
}
|
||
|
if col {
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
false
|
||
|
}
|
||
|
|
||
|
fn sum_unmarked(&self) -> i32 {
|
||
|
let mut sum = 0;
|
||
|
for y in 0..self.numbers.len() {
|
||
|
for x in 0..self.numbers[y].len() {
|
||
|
if !self.marked[y][x] {
|
||
|
sum += self.numbers[y][x];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
sum
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fn main() -> Result<(), Box<dyn Error>> {
|
||
|
let file = File::open("inputs/day4.txt")?;
|
||
|
let mut lines = io::BufReader::new(file).lines().map(|l| l.unwrap());
|
||
|
|
||
|
let numbers_drawn: Vec<i32> = lines
|
||
|
.next()
|
||
|
.unwrap()
|
||
|
.split(",")
|
||
|
.map(|n| n.parse().unwrap())
|
||
|
.collect();
|
||
|
|
||
|
lines.next();
|
||
|
|
||
|
let mut boards: Vec<Board> = Vec::new();
|
||
|
while let Some(board) = Board::from_lines(&mut lines) {
|
||
|
boards.push(board);
|
||
|
}
|
||
|
|
||
|
let mut points_first: Option<i32> = None;
|
||
|
let mut points_last = 0;
|
||
|
for number in numbers_drawn {
|
||
|
for board in boards.iter_mut() {
|
||
|
if !board.has_won() {
|
||
|
board.mark(number);
|
||
|
if board.has_won() {
|
||
|
points_last = board.sum_unmarked() * number;
|
||
|
if points_first.is_none() {
|
||
|
points_first = Some(points_last);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
println!("Answer1: {}", points_first.unwrap());
|
||
|
|
||
|
println!("Answer2: {}", points_last);
|
||
|
|
||
|
Ok(())
|
||
|
}
|