Skip to content

Instantly share code, notes, and snippets.

@robert-king
Created December 3, 2023 00:55
Show Gist options
  • Save robert-king/889c89cdb8ce4dc69c1110cb6370d242 to your computer and use it in GitHub Desktop.
Save robert-king/889c89cdb8ce4dc69c1110cb6370d242 to your computer and use it in GitHub Desktop.
Advent of code day 2, over engineered
// youtube walkthrough: https://youtu.be/mRW8Kbb1YlA?si=lBe4mNvfBYxe9ALl
const DATA: &str = "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";
#[derive(Debug)]
enum Color {
Red,
Blue,
Green,
}
impl Color {
fn new(name: &str) -> Result<Self, String> {
let color = match name {
"red" => Self::Red,
"blue" => Self::Blue,
"green" => Self::Green,
_ => {
return Err(format!("Unknown color {name}"))
}
};
Ok(color)
}
fn is_ok(&self, count: i32) -> bool {
match self {
Color::Red => count <= 12,
Color::Blue => count <= 14,
Color::Green => count <= 13
}
}
}
#[derive(Debug, Default)]
struct GameSet {
counts: Vec<(Color, i32)>
}
impl GameSet {
fn new(part: &str) -> Result<Self, String> {
let mut game_set = GameSet::default();
for color_part in part.split(", ") {
let (count_str, color_str) = color_part.split_once(" ")
.ok_or_else(|| format!("Error parsing color_part {color_part}"))?;
game_set.counts.push(
(
Color::new(color_str)?,
count_str.parse().map_err(|_e| format!("Error parsing count_str {count_str}"))?
)
)
}
Ok(game_set)
}
fn is_ok(&self) -> bool {
return self.counts.iter().all(
|(color, count)| color.is_ok(*count)
)
}
}
#[derive(Debug)]
struct Game {
id: i32,
sets: Vec<GameSet>,
}
impl Game {
fn new(line: &str) -> Result<Self, String> {
let Some((game_part, set_parts)) = line.split_once(": ") else {
return Err(format!("Invalid line {line}"));
};
let Some((_, game_id_str)) = game_part.split_once(" ") else {
return Err(format!("Invalid game part {game_part}"));
};
let mut sets = vec![];
for part in set_parts.split("; ") {
sets.push(GameSet::new(part)?);
}
let Some(id) = game_id_str.parse().ok() else {
return Err(format!("Error parsing num {game_id_str}"))
};
Ok(Game {
id,
sets
})
}
fn is_ok(&self) -> bool {
return self.sets.iter().all(|set| set.is_ok())
}
}
fn main() {
let ans = DATA.lines()
.map(|line| Game::new(line).unwrap())
.filter(|game| game.is_ok())
.map(|valid_game| valid_game.id as i64)
.sum::<i64>();
println!("{ans}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment