|
|
|
@ -6,17 +6,62 @@ const INPUTS: [&'static str; 2] = [
|
|
|
|
|
include_str!("../inputs/day4.txt"),
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
|
const WINNING_COMBINATIONS: [[(usize, usize); 5]; 5] = [
|
|
|
|
|
// Row wins
|
|
|
|
|
[(0, 0), (0, 1), (0, 2), (0, 3), (0, 4)],
|
|
|
|
|
[(1, 0), (1, 1), (1, 2), (1, 3), (1, 4)],
|
|
|
|
|
[(2, 0), (2, 1), (2, 2), (2, 3), (2, 4)],
|
|
|
|
|
[(3, 0), (3, 1), (3, 2), (3, 3), (3, 4)],
|
|
|
|
|
[(4, 0), (4, 1), (4, 2), (4, 3), (4, 4)],
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
|
|
|
|
|
enum BoardEntry {
|
|
|
|
|
Entry(u64),
|
|
|
|
|
CalledEntry(u64),
|
|
|
|
|
Called(u64),
|
|
|
|
|
Null,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
|
|
|
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
|
|
|
|
|
struct Board {
|
|
|
|
|
board: [[BoardEntry; 5]; 5],
|
|
|
|
|
sum: u64,
|
|
|
|
|
won: bool,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Board {
|
|
|
|
|
fn mark_draw(&mut self, draw: u64) {
|
|
|
|
|
for row in self.board.iter_mut() {
|
|
|
|
|
for val in row.iter_mut() {
|
|
|
|
|
if let BoardEntry::Entry(v) = val {
|
|
|
|
|
if *v == draw {
|
|
|
|
|
self.sum -= *v;
|
|
|
|
|
*val = BoardEntry::Called(*v);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_winner(&self) -> bool {
|
|
|
|
|
for set in WINNING_COMBINATIONS.iter() {
|
|
|
|
|
let col_match = set
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|&(x, y)| self.board[y][x])
|
|
|
|
|
.all(|entry| matches!(entry, BoardEntry::Called(_)));
|
|
|
|
|
|
|
|
|
|
let row_match = set
|
|
|
|
|
.iter()
|
|
|
|
|
.map(|&(x, y)| self.board[x][y])
|
|
|
|
|
.all(|entry| matches!(entry, BoardEntry::Called(_)));
|
|
|
|
|
|
|
|
|
|
if row_match || col_match {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn cmds(input: &'static str) -> (Vec<u64>, Vec<Board>) {
|
|
|
|
@ -35,6 +80,7 @@ fn cmds(input: &'static str) -> (Vec<u64>, Vec<Board>) {
|
|
|
|
|
let mut bblock = Board {
|
|
|
|
|
board: [[BoardEntry::Null; 5]; 5],
|
|
|
|
|
sum: 0,
|
|
|
|
|
won: false,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
for (i, line) in block.split('\n').enumerate() {
|
|
|
|
@ -52,63 +98,23 @@ fn cmds(input: &'static str) -> (Vec<u64>, Vec<Board>) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn solution((draws, mut boards): (Vec<u64>, Vec<Board>)) -> u64 {
|
|
|
|
|
for draw in draws {
|
|
|
|
|
// Mark boards
|
|
|
|
|
|
|
|
|
|
mark_entry(&mut boards, draw);
|
|
|
|
|
let mut answer = 0;
|
|
|
|
|
|
|
|
|
|
if let Some(board) = check_winner(&boards) {
|
|
|
|
|
return board.sum * draw;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn check_winner(boards: &[Board]) -> Option<&Board> {
|
|
|
|
|
for board in boards {
|
|
|
|
|
let grid = board.board;
|
|
|
|
|
|
|
|
|
|
for i in 0..5 {
|
|
|
|
|
if grid[i]
|
|
|
|
|
.iter()
|
|
|
|
|
.all(|x| matches!(x, BoardEntry::CalledEntry(_)))
|
|
|
|
|
{
|
|
|
|
|
return Some(board);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
for draw in draws {
|
|
|
|
|
for board in boards.iter_mut() {
|
|
|
|
|
if board.won {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
board.mark_draw(draw);
|
|
|
|
|
|
|
|
|
|
if all_called {
|
|
|
|
|
return Some(board);
|
|
|
|
|
if board.is_winner() {
|
|
|
|
|
answer = board.sum * draw;
|
|
|
|
|
board.won = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
answer
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
@ -121,9 +127,9 @@ fn main() {
|
|
|
|
|
|
|
|
|
|
#[bench]
|
|
|
|
|
fn solution_bench(b: &mut test::Bencher) {
|
|
|
|
|
let input = cmds(INPUTS[1]);
|
|
|
|
|
b.iter(|| {
|
|
|
|
|
let input = cmds(INPUTS[1]);
|
|
|
|
|
let result = solution(input);
|
|
|
|
|
let result = solution(input.clone());
|
|
|
|
|
test::black_box(result);
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|