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;
|
mod prelude;
|
||||||
|
extern crate nom;
|
||||||
|
use crate::prelude::*;
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{tag, take_while_m_n},
|
bytes::complete::{tag, take_while},
|
||||||
combinator::{map_res, value},
|
combinator::{map_res, value},
|
||||||
multi::separated_list0,
|
multi::separated_list0,
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
|
use std::cmp::max;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Day2::show(day_input(2), day_input(2))
|
Day2::show(day_input(2), day_input(2))
|
||||||
}
|
}
|
||||||
|
|
||||||
type Solution = usize;
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
enum Reveal {
|
enum Reveal {
|
||||||
Red(usize),
|
Red(usize),
|
||||||
|
@ -27,68 +21,15 @@ enum Reveal {
|
||||||
Blue(usize),
|
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)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct Game {
|
struct Game {
|
||||||
id: usize,
|
id: usize,
|
||||||
reveal_groups: Vec<RevealGroup>,
|
reveals: Vec<Reveal>,
|
||||||
}
|
|
||||||
|
|
||||||
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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parser
|
||||||
fn int(input: &str) -> IResult<&str, usize> {
|
fn int(input: &str) -> IResult<&str, usize> {
|
||||||
map_res(take_while_m_n(1, 16, |c: char| c.is_numeric()), |s| {
|
map_res(take_while(char::is_numeric), str::parse)(input)
|
||||||
usize::from_str_radix(s, 10)
|
|
||||||
})(input)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reveal(input: &str) -> IResult<&str, Reveal> {
|
fn reveal(input: &str) -> IResult<&str, Reveal> {
|
||||||
|
@ -100,40 +41,44 @@ fn reveal(input: &str) -> IResult<&str, Reveal> {
|
||||||
))(input)
|
))(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> {
|
fn game(input: &str) -> IResult<&str, Game> {
|
||||||
let (input, id) = int(tag("Game ")(input)?.0)?;
|
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 {}
|
struct Day2 {}
|
||||||
impl Day2 {}
|
|
||||||
|
|
||||||
impl AoCSolution for Day2 {
|
impl AoCSolution for Day2 {
|
||||||
type Input = String;
|
type Input = String;
|
||||||
type Solution = Solution;
|
type Solution = usize;
|
||||||
|
|
||||||
fn part1(input: Self::Input) -> Self::Solution {
|
fn part1(input: Self::Input) -> Self::Solution {
|
||||||
const MAX_RED: Solution = 12;
|
let valid = |r: &Reveal| match r {
|
||||||
const MAX_GREEN: Solution = 13;
|
Reveal::Red(n) => *n <= 12,
|
||||||
const MAX_BLUE: Solution = 14;
|
Reveal::Green(n) => *n <= 13,
|
||||||
|
Reveal::Blue(n) => *n <= 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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| game(s).unwrap().1)
|
.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)
|
.map(|g| g.id)
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
|
@ -141,7 +86,7 @@ impl AoCSolution for Day2 {
|
||||||
fn part2(input: Self::Input) -> Self::Solution {
|
fn part2(input: Self::Input) -> Self::Solution {
|
||||||
input
|
input
|
||||||
.lines()
|
.lines()
|
||||||
.map(|s| game(s).unwrap().1.made_possible().power())
|
.map(|s| game(s).unwrap().1.possible_power())
|
||||||
.sum()
|
.sum()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,6 @@ pub use std::io::Read;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::{env, io};
|
use std::{env, io};
|
||||||
|
|
||||||
pub type Reader = Box<dyn Read>;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum InputFileError {
|
enum InputFileError {
|
||||||
VarError(env::VarError),
|
VarError(env::VarError),
|
||||||
|
|
Loading…
Reference in a new issue