day 4 part 1 (not currently working, also massively overcomplicated)
This commit is contained in:
parent
c55a721067
commit
6577bae991
174
2021/src/day4.rs
Normal file
174
2021/src/day4.rs
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
use color_eyre::eyre;
|
||||||
|
use eyre::eyre;
|
||||||
|
|
||||||
|
|
||||||
|
struct Ratchet<T, F>
|
||||||
|
where T: Copy,
|
||||||
|
F: Fn(T) -> u8,
|
||||||
|
{
|
||||||
|
value: Option<T>,
|
||||||
|
getter: F,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, F> Ratchet<T, F>
|
||||||
|
where T: Copy,
|
||||||
|
F: Fn(T) -> u8
|
||||||
|
{
|
||||||
|
fn new(getter: F) -> Self {
|
||||||
|
Ratchet {
|
||||||
|
value: None,
|
||||||
|
getter,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn inc(&mut self, other: T) {
|
||||||
|
match self.value {
|
||||||
|
Some(v) if (self.getter)(other) <= (self.getter)(v) => (),
|
||||||
|
_ => self.value = Some(other),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn dec(&mut self, other: T) {
|
||||||
|
match self.value {
|
||||||
|
Some(v) if (self.getter)(other) >= (self.getter)(v) => (),
|
||||||
|
_ => self.value = Some(other),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct Square {
|
||||||
|
value: u8,
|
||||||
|
draw_time: Option<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default, Debug)]
|
||||||
|
struct Board {
|
||||||
|
squares: [[Square; 5]; 5],
|
||||||
|
bingo_time: Option<u8>,
|
||||||
|
bingo_value: Option<u8>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Board {
|
||||||
|
fn from(squares: &[Square]) -> eyre::Result<Self> {
|
||||||
|
let mut it = squares.iter();
|
||||||
|
let mut b = Self::default();
|
||||||
|
for row in 0..5 {
|
||||||
|
for col in 0..5 {
|
||||||
|
match it.next() {
|
||||||
|
Some(sq) => b.squares[row][col] = *sq,
|
||||||
|
None => return Err(eyre!("Not enough values to populate board")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_bingo(&mut self) {
|
||||||
|
let mut board_bingo = Ratchet::new(|sq: Square| sq.draw_time.unwrap()); // these unwraps are safe because we will only call inc() or dec() after ensuring there is a value there
|
||||||
|
let mut cols_bingo: [bool; 5] = [true; 5];
|
||||||
|
let mut cols_last_drawn: Vec<Ratchet<Square, _>> = (0..5)
|
||||||
|
.map(|_i| Ratchet::new(|sq: Square| sq.draw_time.unwrap()))
|
||||||
|
.collect();
|
||||||
|
// let mut cols_last_drawn: [Ratchet<Square, _>; 5] = [Ratchet::new(|sq: Square| sq.draw_time.unwrap()); 5];
|
||||||
|
for row in self.squares {
|
||||||
|
let mut row_bingo = true;
|
||||||
|
let mut row_last_drawn = Ratchet::new(|sq: Square| sq.draw_time.unwrap());
|
||||||
|
for (col, sq) in row.iter().enumerate() {
|
||||||
|
match sq.draw_time {
|
||||||
|
Some(_) => {
|
||||||
|
row_last_drawn.inc(*sq);
|
||||||
|
cols_last_drawn[col].inc(*sq);
|
||||||
|
},
|
||||||
|
None => {
|
||||||
|
row_bingo = false;
|
||||||
|
cols_bingo[col] = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if row_bingo {
|
||||||
|
let bingo_sq = row_last_drawn.value.unwrap(); // we know there will be a value here if row_bingo is true
|
||||||
|
board_bingo.dec(bingo_sq); //
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for col in 0..5 {
|
||||||
|
if cols_bingo[col] {
|
||||||
|
let bingo_sq = cols_last_drawn[col].value.unwrap(); // similar to above
|
||||||
|
board_bingo.dec(bingo_sq);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(sq) = board_bingo.value {
|
||||||
|
self.bingo_time = sq.draw_time;
|
||||||
|
self.bingo_value = Some(sq.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn score(&self) -> eyre::Result<usize> {
|
||||||
|
let bingo_time = match self.bingo_time {
|
||||||
|
Some(t) => t,
|
||||||
|
None => return Err(eyre!("Cannot find the score of a non-winning board")),
|
||||||
|
};
|
||||||
|
let mut total = 0usize;
|
||||||
|
for row in self.squares {
|
||||||
|
for sq in row {
|
||||||
|
if sq.draw_time.is_some() && sq.draw_time.unwrap() > bingo_time {
|
||||||
|
total += sq.value as usize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(total * self.bingo_value.unwrap() as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn load(data: &str) -> eyre::Result<Vec<Board>> {
|
||||||
|
let mut lines = data.lines().peekable();
|
||||||
|
let mut draws: [Option<u8>; 100] = [None; 100]; // indices are the number drawn, values are the position in which it was drawn
|
||||||
|
for (i, draw) in lines.next().unwrap().split(',').enumerate() {
|
||||||
|
let num = draw.parse::<usize>()?;
|
||||||
|
draws[num] = Some(i.try_into().unwrap()); // will panic if there are more than 256 items in this iterator, but there aren't
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut boards = Vec::new();
|
||||||
|
let mut squares = Vec::new();
|
||||||
|
for line in lines {
|
||||||
|
for s in line.split_whitespace() {
|
||||||
|
let value = s.parse::<u8>()?; // shadows the loop variable I guess?
|
||||||
|
let sq = Square {value, draw_time: draws[value as usize]};
|
||||||
|
squares.push(sq);
|
||||||
|
}
|
||||||
|
if squares.len() == 25 {
|
||||||
|
boards.push(Board::from(&squares)?);
|
||||||
|
boards.last_mut().unwrap().set_bingo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(boards)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn part1(boards: &[Board]) -> eyre::Result<Board> {
|
||||||
|
let winner = boards.iter()
|
||||||
|
.filter(|b| b.bingo_time.is_some())
|
||||||
|
.min_by_key(|b| b.bingo_time.unwrap());
|
||||||
|
|
||||||
|
match winner {
|
||||||
|
Some(w) => Ok(*w),
|
||||||
|
None => Err(eyre!("Could not find a winning board")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn run(data: &str) -> eyre::Result<()> {
|
||||||
|
let boards = load(data)?;
|
||||||
|
let winner = part1(&boards)?;
|
||||||
|
println!("One: {}", winner.score()?);
|
||||||
|
Ok(())
|
||||||
|
}
|
@ -4,13 +4,13 @@ use color_eyre::eyre;
|
|||||||
|
|
||||||
mod lib;
|
mod lib;
|
||||||
use lib::load;
|
use lib::load;
|
||||||
mod day3;
|
mod day4;
|
||||||
|
|
||||||
|
|
||||||
fn main() -> eyre::Result<()> {
|
fn main() -> eyre::Result<()> {
|
||||||
let data = load("data/03.txt")?;
|
let data = load("data/04.txt")?;
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
day3::run(&data)?;
|
day4::run(&data)?;
|
||||||
let (dur, unit) = format_ns(start.elapsed().as_nanos());
|
let (dur, unit) = format_ns(start.elapsed().as_nanos());
|
||||||
println!("Completed in {}{}", dur, unit);
|
println!("Completed in {}{}", dur, unit);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
Loading…
x
Reference in New Issue
Block a user