use std::cmp::Ordering; use crate::day02::CubeType::{Blue, Green, Red, UNKNOWN}; enum CubeType { Red(i32), Green(i32), Blue(i32), UNKNOWN } impl PartialEq for CubeType { fn eq(&self, other: &Self) -> bool { match (self, other) { (Red(first), Red(second )) => first == second, (Green(first), Green(second)) => first == second, (Blue(first), Blue(second )) => first == second, _ => false } } } impl PartialOrd for CubeType { fn partial_cmp(&self, other: &Self) -> Option { match (self, other) { (Red(first), Red(second )) => Some(first.cmp(second)), (Green(first), Green(second)) => Some(first.cmp(second)), (Blue(first), Blue(second )) => Some(first.cmp(second)), _ => None } } } struct CubePull { cubes: Vec } impl Into for String { fn into(self) -> CubePull { let cubes: Vec = self .split(",") .map(|cube_type| cube_type.trim().split_once(" ").unwrap()) .map(|(size_str, color)| (color, size_str.parse::().unwrap())) .map(|data| tuple_to_cube(data)) .collect(); return CubePull{ cubes } } } pub fn execute_task01(content: &str) { let sum_of_failed_games = solve_01(content); assert_eq!(sum_of_failed_games, 2528); println!("Day02 - Task01 - Sum of failed Games: {}", sum_of_failed_games) } pub fn solve_01(content: &str) -> i32{ let red = Red(12); let green = Green(13); let blue = Blue(14); content .lines() .map(|line| { let mut data =line .split(":"); let game_id = extract_game_id(data.next().unwrap()); let data_string = data.next().unwrap(); let num_of_not_possible_pulls = data_string .split(";") .map(|pull| pull.to_string().into()) .map(|cube: CubePull| cube.cubes) .flatten() .filter(|cube| cube.gt(&red) || cube.gt(&green) || cube.gt(&blue)) .count(); return (game_id, num_of_not_possible_pulls > 0) }) .map(|(index, failed)| return if !failed { index } else { 0 }) .sum() } pub fn execute_task02(content: &str) { let sum = solve_02(content); assert_eq!(sum, 67363); println!("Day02 - Task02 - Sum of power of min. Cubes: {}", sum) } pub fn solve_02(content: &str) -> i32{ content .lines() .map(|line| { let data_string = line.split(":").last().unwrap(); let mut red = 0; let mut green = 0; let mut blue = 0; data_string .split(";") .map(|pull| pull.to_string().into()) .map(|cube: CubePull| cube.cubes) .flatten() .for_each(|cube_type| match cube_type { Red(size) => if size > red { red = size } Green(size) => if size > green { green = size } Blue(size) => if size > blue { blue = size } _ => {} }); return red * blue * green }) .sum() } fn extract_game_id(name: &str) -> i32 { name.split(' ').last().map(|data| data.parse().unwrap()).unwrap() } fn tuple_to_cube((color, size): (&str, i32)) -> CubeType { match color { "red" => Red(size), "green" => Green(size), "blue" => Blue(size), _ => UNKNOWN } } #[test] fn test_solve_01() { let test_input = r#"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"#; let solution = solve_01(test_input); assert_eq!(8, solution); } #[test] fn test_solve_02() { let test_input = r#"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"#; let solution = solve_02(test_input); assert_eq!(2286, solution); }