diff --git a/data/examples/02.txt b/data/examples/02.txt new file mode 100644 index 0000000..295c36d --- /dev/null +++ b/data/examples/02.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/02.rs b/src/bin/02.rs new file mode 100644 index 0000000..707f970 --- /dev/null +++ b/src/bin/02.rs @@ -0,0 +1,86 @@ +advent_of_code::solution!(2); + +use std::collections::HashMap; + +pub fn part_one(input: &str) -> Option { + let max_cubes = HashMap::from([("red", 12), ("green", 13), ("blue", 14)]); + + // Game ID + let mut index: u32 = 1; + + input + .lines() + .map(|game| { + let mut possible_game = true; // assume that games are possible by default + + // Extract sets from game + // - Referencing the string slice is faster than splitting with ": " + // - Ignoring the ID, 'Game ID: ' has 7 constant chars. + // - To calculate the ID length, we use log10: id_length = log10(index) + 1 + let sets: &Vec<&str> = &game[(7 + index.checked_ilog10().unwrap_or(0) + 1) + .try_into() + .unwrap()..] + .split("; ") + .collect::>(); + + // Determine if the game is possible for each set + for set in sets { + let cubes = set + .split(", ") + .map(|x| x.split(' ').collect::>()) + .collect::>(); + + // Compare examined cubes with maximum values + for cube in cubes.iter() { + let color = cube[1]; + let number = cube[0].parse::().unwrap(); + let max_number = *max_cubes.get(color).unwrap(); + + // If the game is impossible, skip the rest of the cubes + if number > max_number { + possible_game = false; + break; + } + } + + // If the game is impossible, skip its unchecked sets + if possible_game == false { + break; + } + } + + // Move on to the next game + index += 1; + + if possible_game == true { + // We need to remove 1 since index starts from 1, not 0 + index - 1 + } else { + 0 + } + }) + .sum::() + .try_into() + .ok() +} + +pub fn part_two(_input: &str) -> Option { + None +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_part_one() { + let result = part_one(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, Some(8)); + } + + #[test] + fn test_part_two() { + let result = part_two(&advent_of_code::template::read_file("examples", DAY)); + assert_eq!(result, None); + } +}