use itertools::Itertools; pub fn process_part1(input: &str) -> i64 { input .split(',') .map(|range| range.split_once('-').unwrap()) .map(|(start, end)| { ( start .parse::() .expect(&format!("Cannot parse start from {start}")), end.trim_end() .parse::() .expect(&format!("Cannot parse end from {end}")), ) }) .map(|(start, end)| { (start..=end) .map(|id| { let id_str = format!("{id}"); if id_str.starts_with('0') { return 0; } let (left, right) = id_str.split_at(id_str.len() / 2); if left == right { return id; } 0 }) .sum::() }) .sum() } pub fn process_part2(input: &str) -> i64 { input .split(',') .map(|range| range.split_once('-').unwrap()) .map(|(start, end)| { ( start .parse::() .expect(&format!("Cannot parse start from {start}")), end.trim_end() .parse::() .expect(&format!("Cannot parse end from {end}")), ) }) .map(|(start, end)| { (start..=end) .map(|id| { let id_str = format!("{id}"); if id_str.starts_with('0') { return 0; } for num_parts in 2..=id_str.len() { let parts = id_str .chars() .chunks(id_str.len() / num_parts) .into_iter() .map(|chunk| chunk.collect::()) .collect::>(); if parts.iter().all_equal() { return id; } } 0 }) .sum::() }) .sum() } #[cfg(test)] mod tests { use super::*; const INPUT: &str = "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"; #[test] fn part1() { let result = process_part1(INPUT); assert_eq!(result, 1227775554); } #[test] fn part2() { let result = process_part2(INPUT); assert_eq!(result, 4174379265); } }