2021-12-01 05:51:55 +00:00
|
|
|
#![feature(test)]
|
|
|
|
extern crate test;
|
|
|
|
|
2021-12-03 05:38:45 +00:00
|
|
|
const INPUTS: [&'static str; 2] = [
|
2021-12-04 05:41:16 +00:00
|
|
|
include_str!("../inputs/day4.sample.txt"),
|
|
|
|
include_str!("../inputs/day4.txt"),
|
2021-12-03 05:38:45 +00:00
|
|
|
];
|
2021-12-02 05:14:07 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
enum BoardEntry {
|
|
|
|
Entry(u64),
|
|
|
|
CalledEntry(u64),
|
|
|
|
Null,
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
struct Board {
|
|
|
|
board: [[BoardEntry; 5]; 5],
|
|
|
|
sum: u64,
|
2021-12-03 13:33:56 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
fn cmds(input: &'static str) -> (Vec<u64>, Vec<Board>) {
|
|
|
|
let mut lines = input.split("\n\n").filter(|x| !x.is_empty());
|
|
|
|
|
|
|
|
let draws: Vec<u64> = lines
|
|
|
|
.next()
|
|
|
|
.unwrap()
|
|
|
|
.split(',')
|
|
|
|
.map(|x| x.parse::<u64>().unwrap())
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
let mut boards = vec![];
|
|
|
|
|
|
|
|
for block in lines {
|
|
|
|
let mut bblock = Board {
|
|
|
|
board: [[BoardEntry::Null; 5]; 5],
|
|
|
|
sum: 0,
|
|
|
|
};
|
|
|
|
|
|
|
|
for (i, line) in block.split('\n').enumerate() {
|
|
|
|
for (j, c) in line.split(' ').filter(|x| !x.is_empty()).enumerate() {
|
|
|
|
let num = c.parse::<u64>().unwrap();
|
|
|
|
bblock.board[i][j] = BoardEntry::Entry(num);
|
|
|
|
bblock.sum += num;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
boards.push(bblock)
|
|
|
|
}
|
|
|
|
|
|
|
|
(draws, boards)
|
|
|
|
}
|
2021-12-03 13:33:56 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
fn solution((draws, mut boards): (Vec<u64>, Vec<Board>)) -> u64 {
|
|
|
|
for draw in draws {
|
|
|
|
// Mark boards
|
2021-12-03 13:33:56 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
mark_entry(&mut boards, draw);
|
2021-12-03 13:33:56 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
if let Some(board) = check_winner(&boards) {
|
|
|
|
return board.sum * draw;
|
|
|
|
}
|
2021-12-03 05:38:45 +00:00
|
|
|
}
|
2021-12-02 05:14:07 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
0
|
2021-12-02 05:18:04 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
fn check_winner(boards: &[Board]) -> Option<&Board> {
|
|
|
|
for board in boards {
|
|
|
|
let grid = board.board;
|
2021-12-03 05:38:45 +00:00
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
for i in 0..5 {
|
|
|
|
if grid[i]
|
|
|
|
.iter()
|
|
|
|
.all(|x| matches!(x, BoardEntry::CalledEntry(_)))
|
|
|
|
{
|
|
|
|
return Some(board);
|
2021-12-02 05:18:04 +00:00
|
|
|
}
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
for j in 0..5 {
|
|
|
|
let mut all_called = true;
|
|
|
|
for i in 0..5 {
|
|
|
|
if !matches!(grid[i][j], BoardEntry::CalledEntry(_)) {
|
|
|
|
all_called = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if all_called {
|
|
|
|
return Some(board);
|
|
|
|
}
|
2021-12-03 05:38:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-04 05:41:16 +00:00
|
|
|
None
|
|
|
|
}
|
|
|
|
|
|
|
|
fn mark_entry(boards: &mut [Board], called: u64) {
|
|
|
|
for board in boards {
|
|
|
|
for row in board.board.iter_mut() {
|
|
|
|
for col in row.iter_mut() {
|
|
|
|
if let BoardEntry::Entry(val) = col {
|
|
|
|
if *val == called {
|
|
|
|
board.sum -= *val;
|
|
|
|
*col = BoardEntry::CalledEntry(*val);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-03 05:38:45 +00:00
|
|
|
}
|
2021-12-01 05:51:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn main() {
|
2021-12-04 05:41:16 +00:00
|
|
|
for input in INPUTS {
|
|
|
|
let input = cmds(input);
|
|
|
|
let result = solution(input);
|
|
|
|
println!("Result {}", result);
|
|
|
|
}
|
2021-12-01 05:16:08 +00:00
|
|
|
}
|
2021-12-01 05:51:55 +00:00
|
|
|
|
|
|
|
#[bench]
|
|
|
|
fn solution_bench(b: &mut test::Bencher) {
|
|
|
|
b.iter(|| {
|
2021-12-04 05:41:16 +00:00
|
|
|
let input = cmds(INPUTS[1]);
|
|
|
|
let result = solution(input);
|
|
|
|
test::black_box(result);
|
2021-12-01 05:51:55 +00:00
|
|
|
})
|
|
|
|
}
|