diff --git a/src/bin/day02.rs b/src/bin/day02.rs new file mode 100644 index 0000000..d7cb873 --- /dev/null +++ b/src/bin/day02.rs @@ -0,0 +1,80 @@ +use color_eyre::{ + eyre::{bail, ContextCompat}, + Report, Result, +}; +use std::io::stdin; + +fn n_colour_pair(input: &str) -> Result<(u64, &str)> { + let (n, c) = input + .trim() + .split_once(' ') + .context("Invalid poll format; expected: ")?; + + Ok((n.parse()?, c)) +} + +fn part1(id: u64, game: &str) -> Result { + let and_reducer = |acc, x| Ok(acc && x?); + + Ok(game + .split(';') + .map(|game| -> Result { + game.split(',') + .map(|poll| -> Result { + let (count, colour) = n_colour_pair(poll)?; + Ok(match colour { + "red" if count <= 12 => true, + "green" if count <= 13 => true, + "blue" if count <= 14 => true, + "red" | "green" | "blue" => false, + c => { + bail!("Invalid colour: {c}, expected red, green or blue") + } + }) + }) + .try_fold(true, and_reducer) + }) + .try_fold(true, and_reducer)? + .then_some(id) + .unwrap_or_default()) +} + +fn part2(_: u64, game: &str) -> Result { + game.split([',', ';']) + .try_fold([0; 3], |mut acc, seg| { + let (count, colour) = n_colour_pair(seg)?; + let i = match colour { + "red" => 0, + "green" => 1, + "blue" => 2, + c => bail!("Invalid colour: {c}, expected red, green or blue"), + }; + + acc[i] = acc[i].max(count); + Ok(acc) + }) + .map(|arr| arr.iter().product()) +} + +fn main() -> Result<()> { + //let part = part1; + let part = part2; + + Ok(println!( + "{}", + stdin() + .lines() + .map(|ln| { + ln.map_err(Report::from).and_then(|ln| { + let (id, game) = ln.split_once(':').context("Invalid ID")?; + let id: u64 = id + .strip_prefix("Game ") + .context("ID should start with \"Game \"")? + .parse()?; + + part(id, game) + }) + }) + .try_fold::<_, _, Result>(0, |acc, x| Ok(acc + x?))? + )) +}