diff --git a/samples/day02.txt b/samples/day02.txt new file mode 100644 index 0000000..295c36d --- /dev/null +++ b/samples/day02.txt @@ -0,0 +1,5 @@ +Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green +Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue +Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red +Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red +Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green diff --git a/src/bin/day02.rs b/src/bin/day02.rs new file mode 100644 index 0000000..faf7e50 --- /dev/null +++ b/src/bin/day02.rs @@ -0,0 +1,133 @@ +use std::str::FromStr; + +use aoc_2023::*; + +type Output1 = i32; +type Output2 = Output1; + +#[derive(Debug, PartialEq)] +struct Pick { + red: i32, + green: i32, + blue: i32, +} + +impl Pick { + fn new() -> Pick { + Pick { + red: 0, + green: 0, + blue: 0, + } + } +} + +impl FromStr for Pick { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + Ok(s.split(',') + .map(|s| s.trim()) + .fold(Pick::new(), |mut p, s| { + let mut parts = s.split_whitespace(); + + let count: i32 = parts.next().unwrap().parse().unwrap(); + match parts.next().unwrap() { + "red" => { + p.red = count; + } + "green" => { + p.green = count; + } + "blue" => { + p.blue = count; + } + _ => unreachable!("invalid color"), + } + + p + })) + } +} + +struct Game { + id: i32, + picks: Vec, +} + +impl FromStr for Game { + type Err = &'static str; + + fn from_str(s: &str) -> Result { + let mut parts = s.split(':'); + let mut left = parts.next().unwrap().split_ascii_whitespace(); + + let id: i32 = left.nth(1).unwrap().parse().unwrap(); + + let picks = parts + .next() + .unwrap() + .split(';') + .map(|p| p.trim().parse().unwrap()) + .collect_vec(); + + Ok(Game { id, picks }) + } +} + +impl Game { + fn possible(&self, r: i32, g: i32, b: i32) -> bool { + self.picks + .iter() + .all(|p| p.red <= r && p.green <= g && p.blue <= b) + } + + fn min(&self) -> (i32, i32, i32) { + ( + self.picks.iter().map(|p| p.red).max().unwrap(), + self.picks.iter().map(|p| p.green).max().unwrap(), + self.picks.iter().map(|p| p.blue).max().unwrap(), + ) + } +} + +struct Day02 { + games: Vec, +} +impl Solution for Day02 { + fn new>(pathname: P) -> Self { + Self { + games: file_to_structs(pathname), + } + } + + fn part_1(&mut self) -> Output1 { + self.games + .iter() + .filter_map(|g| { + if g.possible(12, 13, 14) { + Some(g.id) + } else { + None + } + }) + .sum() + } + + fn part_2(&mut self) -> Output2 { + self.games + .iter() + .map(|g| { + let (r, g, b) = g.min(); + + r * g * b + }) + .sum() + } +} + +fn main() -> Result<()> { + Day02::main() +} + +test_sample!(day_02, Day02, 8, 2286);