pub fn execute_task01(content: &str) { let sum_of_machine_parts = solve_01(content); println!("Day03 - Task01 - Sum of Machine-Parts: {}", sum_of_machine_parts) } pub fn execute_task02(content: &str) { let sum_of_machine_parts = solve_02(content); println!("Day03 - Task02 - Sum of Machine-Gears: {}", sum_of_machine_parts) } pub fn solve_01(content: &str) -> i32 { let map: Vec> = content.lines().map(|line| line.chars().collect()).collect(); let (machine_parts, _) = parse_to_parts(map); return machine_parts.iter().map(|number| number.parse::().unwrap()).sum(); } pub fn solve_02(content: &str) -> i32 { let map: Vec> = content.lines().map(|line| line.chars().collect()).collect(); let mut data = 0; for (row_index, row) in map.iter().enumerate() { for (col_index, char) in row.iter().enumerate() { if char == &'*' { let numbers = get_numbers_around(&map, row_index, col_index); if numbers.len() <= 1 { continue } data += numbers .iter() .map(|data| data.parse::().unwrap()).product::(); } } } return data; } fn get_numbers_around(map: &Vec>, row: usize, col: usize) -> Vec { let mut nums = vec![]; let mut data = String::new(); if row > 0 { let row_data = map.get(row - 1).unwrap(); let mut data = String::new(); if col > 0 { if row_data.get(col - 1).unwrap().is_ascii_digit() { data.push(row_data.get(col - 1).unwrap().clone()); let mut i = 2; while (col as i32 - i as i32) >= 0 { if let Some(char) = row_data.get(col - i) { if char.is_ascii_digit() { data = char.to_string() + data.as_str(); } else { break; } } else { break; } i += 1; } } } if row_data.get(col).unwrap().is_ascii_digit() { data.push(row_data.get(col).unwrap().clone()) } else { if data.len() > 0 { nums.push(data); data = String::new() } } if row_data.len() - 1 > col { if row_data.get(col + 1).unwrap().is_ascii_digit() { data.push(row_data.get(col + 1).unwrap().clone()); let mut i = 2; while (col + i) < row_data.len() { if let Some(char) = row_data.get(col + i) { if char.is_ascii_digit() { data.push(char.clone()) } else { break; } } else { break; } i += 1; } } } if data.len() > 0 { nums.push(data); data = String::new() } } let row_data = map.get(row).unwrap(); if col > 0 { if row_data.get(col - 1).unwrap().is_ascii_digit() { data.push(row_data.get(col - 1).unwrap().clone()); let mut i = 2; while (col as i32 - i as i32) >= 0 { if let Some(char) = row_data.get(col - i) { if char.is_ascii_digit() { data = char.to_string() + data.as_str(); } else { break; } } else { break; } i += 1; } } } if data.len() > 0 { nums.push(data); data = String::new() } if row_data.len() - 1 > col { if row_data.get(col + 1).unwrap().is_ascii_digit() { data.push(row_data.get(col + 1).unwrap().clone()); let mut i = 2; while (col + i) < row_data.len() { if let Some(char) = row_data.get(col + i) { if char.is_ascii_digit() { data.push(char.clone()) } else { break; } } else { break; } i += 1; } } } if data.len() > 0 { nums.push(data); data = String::new() } if map.len() - 1 > row { let row_data = map.get(row + 1).unwrap(); let mut data = String::new(); if col > 0 { if row_data.get(col - 1).unwrap().is_ascii_digit() { data.push(row_data.get(col - 1).unwrap().clone()); let mut i = 2; while (col as i32 - i as i32) >= 0 { if let Some(char) = row_data.get(col - i) { if char.is_ascii_digit() { data = char.to_string() + data.as_str(); } else { break; } } else { break; } i += 1; } } } if row_data.get(col).unwrap().is_ascii_digit() { data.push(row_data.get(col).unwrap().clone()) } else { if data.len() > 0 { nums.push(data); data = String::new() } } if row_data.len() - 1 > col { if row_data.get(col + 1).unwrap().is_ascii_digit() { data.push(row_data.get(col + 1).unwrap().clone()); let mut i = 2; while (col + i) < row_data.len() { if let Some(char) = row_data.get(col + i) { if char.is_ascii_digit() { data.push(char.clone()) } else { break; } } else { break; } i += 1; } } } if data.len() > 0 { nums.push(data); data = String::new() } } return nums; } fn get_cords_around(row: usize, col: usize, max_row: usize, max_col: usize) -> Vec<(usize, usize)> { let mut cords = vec![]; if row > 0 { if col > 0 { cords.push((row - 1, col - 1)); } cords.push((row - 1, col)); if max_col - 1 > col { cords.push((row - 1, col + 1)); } } if col > 0 { cords.push((row, col - 1)); } if max_col - 1 > col { cords.push((row, col + 1)); } if max_row - 1 > row { if col > 0 { cords.push((row + 1, col - 1)); } cords.push((row + 1, col)); if max_col - 1 > col { cords.push((row + 1, col + 1)); } } return cords; } fn parse_to_parts(map: Vec>) -> (Vec, Vec) { let mut machine_part = vec![]; let mut non_machine_part = vec![]; for (row_index, row) in map.iter().enumerate() { let mut machine = String::new(); let mut is_machine = false; for (col_index, char) in row.iter().enumerate() { if !char.is_ascii_digit() { if machine.len() == 0 { continue } if is_machine { machine_part.push(machine) } else { non_machine_part.push(machine) } machine = String::new(); is_machine = false; continue } machine.push(char.clone()); if has_symbol_around(&map, row_index, col_index) { is_machine = true } } if machine.len() > 0 { if is_machine { machine_part.push(machine) } else { non_machine_part.push(machine) } } } return (machine_part, non_machine_part) } fn has_symbol_around(map: &Vec>, row: usize, col: usize) -> bool { if row > 0 { let row_data = map.get(row - 1).unwrap(); if col > 0 { let character = row_data.get(col - 1).unwrap(); if is_symbol(character) { return true } } let character = row_data.get(col).unwrap(); if is_symbol(character) { return true } if row_data.len() - 1 > col { let character = row_data.get(col + 1).unwrap(); if is_symbol(character) { return true } } } let row_data = map.get(row).unwrap(); if col > 0 { let character = row_data.get(col - 1).unwrap(); if is_symbol(character) { return true } } if row_data.len() - 1 > col { let character = row_data.get(col + 1).unwrap(); if is_symbol(character) { return true } } if map.len() - 1 > row { let row_data = map.get(row + 1).unwrap(); if col > 0 { let character = row_data.get(col - 1).unwrap(); if is_symbol(character) { return true } } let character = row_data.get(col).unwrap(); if is_symbol(character) { return true } if row_data.len() - 1 > col { let character = row_data.get(col + 1).unwrap(); if is_symbol(character) { return true } } } return false } pub fn is_symbol(character: &char) -> bool { let result = match character { '.' => false, '0'..='9' => false, _ => true }; return result; } #[test] fn test_solve_01() { let test_input = r#"467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.."#; let solution = solve_01(test_input); assert_eq!(4361, solution); } #[test] fn test_solve_02() { let test_input = r#"467..114.. ...*...... ..35..633. ......#... 617*...... .....+.58. ..592..... ......755. ...$.*.... .664.598.."#; let solution = solve_02(test_input); assert_eq!(467835, solution); } #[test] fn test_solve_01_2() { let test_input = r#"...... .12*34 ......"#; let solution = solve_01(test_input); assert_eq!(46, solution); } #[test] fn test1() { let data = vec![ vec!['.','.','.','#','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','.','#','.','#','.','1'], vec!['.','1','.','.','2','.','#','3','.','.','4','.','.','5','.','6','.','.','7','#','.','8','.','.','9','.','2'], vec!['.','.','.','.','.','.','.','.','.','#','.','.','.','#','.','.','#','.','.','.','.','.','.','.','.','.','3'] ]; assert_eq!(false, has_symbol_around(&data, 1, 1)); assert_eq!(true, has_symbol_around(&data, 1, 4)); assert_eq!(true, has_symbol_around(&data, 1, 7)); assert_eq!(true, has_symbol_around(&data, 1, 10)); assert_eq!(true, has_symbol_around(&data, 1, 13)); assert_eq!(true, has_symbol_around(&data, 1, 15)); assert_eq!(true, has_symbol_around(&data, 1, 18)); assert_eq!(true, has_symbol_around(&data, 1, 21)); assert_eq!(true, has_symbol_around(&data, 1, 24)); assert_eq!(false, has_symbol_around(&data, 0, 26)); assert_eq!(false, has_symbol_around(&data, 1, 26)); assert_eq!(false, has_symbol_around(&data, 2, 26)); }