Cleanup
This commit is contained in:
parent
c89d892343
commit
5631415039
|
@ -1,25 +1,19 @@
|
|||
use std::cmp::{max, min};
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
extern crate nom;
|
||||
|
||||
mod prelude;
|
||||
|
||||
extern crate nom;
|
||||
use crate::prelude::*;
|
||||
use nom::{
|
||||
branch::alt,
|
||||
bytes::complete::{tag, take_while_m_n},
|
||||
bytes::complete::{tag, take_while},
|
||||
combinator::{map_res, value},
|
||||
multi::separated_list0,
|
||||
IResult,
|
||||
};
|
||||
use std::cmp::max;
|
||||
|
||||
fn main() {
|
||||
Day2::show(day_input(2), day_input(2))
|
||||
}
|
||||
|
||||
type Solution = usize;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum Reveal {
|
||||
Red(usize),
|
||||
|
@ -27,68 +21,15 @@ enum Reveal {
|
|||
Blue(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct RevealGroup {
|
||||
red: Option<usize>,
|
||||
green: Option<usize>,
|
||||
blue: Option<usize>,
|
||||
}
|
||||
|
||||
impl RevealGroup {
|
||||
fn power(&self) -> usize {
|
||||
println!("reveal group power for {:?}", self);
|
||||
self.red.unwrap_or(0) * self.green.unwrap_or(0) * self.blue.unwrap_or(0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Vec<Reveal>> for RevealGroup {
|
||||
fn from(value: Vec<Reveal>) -> Self {
|
||||
// TODO: this obviously won't work if the vector contains multiple reveals of the same kind
|
||||
// there's probably a simpler way to parse it out
|
||||
let mut result = Self {
|
||||
red: None,
|
||||
blue: None,
|
||||
green: None,
|
||||
};
|
||||
for v in value {
|
||||
match v {
|
||||
Reveal::Red(v) => result.red = Some(v),
|
||||
Reveal::Green(v) => result.green = Some(v),
|
||||
Reveal::Blue(v) => result.blue = Some(v),
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Game {
|
||||
id: usize,
|
||||
reveal_groups: Vec<RevealGroup>,
|
||||
}
|
||||
|
||||
impl Game {
|
||||
fn made_possible(&self) -> RevealGroup {
|
||||
let mut red = 0;
|
||||
let mut green = 0;
|
||||
let mut blue = 0;
|
||||
for rg in &self.reveal_groups {
|
||||
red = max(rg.red.unwrap_or(0), red);
|
||||
green = max(rg.green.unwrap_or(0), green);
|
||||
blue = max(rg.blue.unwrap_or(0), blue);
|
||||
}
|
||||
RevealGroup {
|
||||
red: Some(red),
|
||||
green: Some(green),
|
||||
blue: Some(blue),
|
||||
}
|
||||
}
|
||||
reveals: Vec<Reveal>,
|
||||
}
|
||||
|
||||
// parser
|
||||
fn int(input: &str) -> IResult<&str, usize> {
|
||||
map_res(take_while_m_n(1, 16, |c: char| c.is_numeric()), |s| {
|
||||
usize::from_str_radix(s, 10)
|
||||
})(input)
|
||||
map_res(take_while(char::is_numeric), str::parse)(input)
|
||||
}
|
||||
|
||||
fn reveal(input: &str) -> IResult<&str, Reveal> {
|
||||
|
@ -100,40 +41,44 @@ fn reveal(input: &str) -> IResult<&str, Reveal> {
|
|||
))(input)
|
||||
}
|
||||
|
||||
fn reveal_group(input: &str) -> IResult<&str, RevealGroup> {
|
||||
let (input, reveals) = separated_list0(tag(", "), reveal)(input)?;
|
||||
Ok((input, RevealGroup::from(reveals)))
|
||||
}
|
||||
|
||||
fn game(input: &str) -> IResult<&str, Game> {
|
||||
let (input, id) = int(tag("Game ")(input)?.0)?;
|
||||
let (input, reveal_groups) = separated_list0(tag("; "), reveal_group)(tag(": ")(input)?.0)?;
|
||||
let (input, reveals) =
|
||||
separated_list0(alt((tag(", "), tag("; "))), reveal)(tag(": ")(input)?.0)?;
|
||||
Ok((input, Game { id, reveals }))
|
||||
}
|
||||
|
||||
Ok((input, Game { id, reveal_groups }))
|
||||
impl Game {
|
||||
fn possible_power(&self) -> usize {
|
||||
// TODO: probably the last place to cleanup nicely
|
||||
let mut factors: [usize; 3] = [0, 0, 0];
|
||||
for r in &self.reveals {
|
||||
match r {
|
||||
Reveal::Red(n) => factors[0] = max(*n, factors[0]),
|
||||
Reveal::Green(n) => factors[1] = max(*n, factors[1]),
|
||||
Reveal::Blue(n) => factors[2] = max(*n, factors[2]),
|
||||
}
|
||||
}
|
||||
factors.iter().fold(1, |a, b| a * b)
|
||||
}
|
||||
}
|
||||
|
||||
struct Day2 {}
|
||||
impl Day2 {}
|
||||
|
||||
impl AoCSolution for Day2 {
|
||||
type Input = String;
|
||||
type Solution = Solution;
|
||||
type Solution = usize;
|
||||
|
||||
fn part1(input: Self::Input) -> Self::Solution {
|
||||
const MAX_RED: Solution = 12;
|
||||
const MAX_GREEN: Solution = 13;
|
||||
const MAX_BLUE: Solution = 14;
|
||||
|
||||
let valid_reveal_group = |rg: &RevealGroup| {
|
||||
rg.red.unwrap_or(0) <= MAX_RED
|
||||
&& rg.green.unwrap_or(0) <= MAX_GREEN
|
||||
&& rg.blue.unwrap_or(0) <= MAX_BLUE
|
||||
let valid = |r: &Reveal| match r {
|
||||
Reveal::Red(n) => *n <= 12,
|
||||
Reveal::Green(n) => *n <= 13,
|
||||
Reveal::Blue(n) => *n <= 14,
|
||||
};
|
||||
|
||||
input
|
||||
.lines()
|
||||
.map(|s| game(s).unwrap().1)
|
||||
.filter(|g| g.reveal_groups.iter().all(valid_reveal_group))
|
||||
.filter(|g| g.reveals.iter().all(valid))
|
||||
.map(|g| g.id)
|
||||
.sum()
|
||||
}
|
||||
|
@ -141,7 +86,7 @@ impl AoCSolution for Day2 {
|
|||
fn part2(input: Self::Input) -> Self::Solution {
|
||||
input
|
||||
.lines()
|
||||
.map(|s| game(s).unwrap().1.made_possible().power())
|
||||
.map(|s| game(s).unwrap().1.possible_power())
|
||||
.sum()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ pub use std::io::Read;
|
|||
use std::path::{Path, PathBuf};
|
||||
use std::{env, io};
|
||||
|
||||
pub type Reader = Box<dyn Read>;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum InputFileError {
|
||||
VarError(env::VarError),
|
||||
|
|
Loading…
Reference in a new issue