diff --git a/aoc_utils/python_versions.txt b/aoc_utils/python_versions.txt index 048063e..a16f355 100644 --- a/aoc_utils/python_versions.txt +++ b/aoc_utils/python_versions.txt @@ -1,7 +1,9 @@ -3.7 3.8 3.9 3.10 3.11 3.12 +3.13 +3.14 pypy3.10 +pypy3.11 diff --git a/aoc_utils/src/lib.rs b/aoc_utils/src/lib.rs index 6988d19..cb10b3e 100644 --- a/aoc_utils/src/lib.rs +++ b/aoc_utils/src/lib.rs @@ -3,6 +3,10 @@ use std::collections::{HashMap, HashSet}; use std::fs::read_to_string; use std::ops::RemAssign; +pub fn read_line(filename: &str) -> String { + read_to_string(filename).unwrap() +} + pub fn read_lines(filename: &str) -> Vec { read_to_string(filename) .unwrap() diff --git a/year_2025/input/day2.txt b/year_2025/input/day2.txt new file mode 100644 index 0000000..c2d817f --- /dev/null +++ b/year_2025/input/day2.txt @@ -0,0 +1 @@ +52500467-52574194,655624494-655688785,551225-576932,8418349387-8418411293,678-1464,33-79,74691-118637,8787869169-8787890635,9898977468-9899009083,548472423-548598890,337245835-337375280,482823-543075,926266-991539,1642682920-1642753675,3834997-3940764,1519-2653,39697698-39890329,3-21,3251796-3429874,3467-9298,26220798-26290827,80-124,200638-280634,666386-710754,21329-64315,250-528,9202893-9264498,819775-903385,292490-356024,22-32,2663033-2791382,133-239,56514707-56704320,432810-458773,4949427889-4949576808 \ No newline at end of file diff --git a/year_2025/src/day2.rs b/year_2025/src/day2.rs new file mode 100644 index 0000000..beaaf4e --- /dev/null +++ b/year_2025/src/day2.rs @@ -0,0 +1,104 @@ +pub fn execute() -> String { + let data = aoc_utils::read_line("input/day2.txt"); + + let part1 = get_all_invalids(&data, false).iter().sum::(); + let part2 = get_all_invalids(&data, true).iter().sum::(); + + format!("{} {}", part1, part2) +} +type ProductID = usize; + +fn get_all_invalids(data: &String, any_splits: bool) -> Vec { + let ranges = parse_ranges(&data); + ranges + .iter() + .flat_map(|range| get_invalid_ids_in_range(range, any_splits)) + .collect() +} + +fn get_invalid_ids_in_range(range: &(ProductID, ProductID), any_splits: bool) -> Vec { + let mut invalids = vec![]; + + for n in range.0..range.1 + 1 { + if !is_valid_id(n, any_splits) { + invalids.push(n); + } + } + + invalids +} + +fn is_valid_id(n: ProductID, any_splits: bool) -> bool { + let digits = f32::log10(n as f32) as usize + 1; + assert!(digits > 0); + + let max_splits = if any_splits { digits } else { 2 }; + + for splits in 2..max_splits + 1 { + if digits % splits == 0 { + if is_invalid_id(n, splits) { + return false; + } + } + } + return true; +} + +fn is_invalid_id(n: ProductID, splits: usize) -> bool { + let text = n.to_string().chars().collect::>(); + let digits = text.len(); + + for s in 1..splits { + for i in 0..digits / splits { + if text[i] != text[i + s * digits / splits] { + return false; + } + } + } + true +} + +fn parse_ranges(data: &String) -> Vec<(ProductID, ProductID)> { + data.split(',') + .map(|range| { + let mut split = range.split('-'); + ( + split.next().unwrap().parse::().unwrap(), + split.next().unwrap().parse::().unwrap(), + ) + }) + .collect() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_example() { + let data = example(); + + let all_invalids = get_all_invalids(&data, false); + assert_eq!(all_invalids.iter().sum::(), 1227775554); + + let all_invalids_really = get_all_invalids(&data, true); + assert_eq!(all_invalids_really.iter().sum::(), 4174379265); + } + #[test] + fn test_mine() { + assert_eq!(execute(), "41294979841 66500947346"); + } + + #[test] + fn test_parse_ranges() { + let ranges = parse_ranges(&example()); + assert_eq!(ranges.len(), 11); + for range in ranges { + assert!(range.0 < range.1); + } + } + + fn example() -> String { + "11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124".to_string() + } +} diff --git a/year_2025/src/main.rs b/year_2025/src/main.rs index 21b7235..166098e 100644 --- a/year_2025/src/main.rs +++ b/year_2025/src/main.rs @@ -1,5 +1,7 @@ mod day1; +mod day2; fn main() { println!("Day 1: {}", day1::execute()); + println!("Day 2: {}", day2::execute()); }