diff --git a/aoc2025/benches/aoc2025_bench.rs b/aoc2025/benches/aoc2025_bench.rs index 6f8d4de..73c5a0c 100644 --- a/aoc2025/benches/aoc2025_bench.rs +++ b/aoc2025/benches/aoc2025_bench.rs @@ -1,11 +1,9 @@ use criterion::{criterion_group, criterion_main, Criterion}; use aoc2025::day01; -use aoc2025::day02; fn aoc2025_all(c: &mut Criterion) { c.bench_function("day01", |b| b.iter(|| day01::run().unwrap())); - c.bench_function("day02", |b| b.iter(|| day02::run().unwrap())); } criterion_group! { diff --git a/aoc2025/input/day02.txt b/aoc2025/input/day02.txt deleted file mode 100644 index 2bc9ca3..0000000 --- a/aoc2025/input/day02.txt +++ /dev/null @@ -1 +0,0 @@ -52-75,71615244-71792700,89451761-89562523,594077-672686,31503-39016,733-976,1-20,400309-479672,458-635,836793365-836858811,3395595155-3395672258,290-391,5168-7482,4545413413-4545538932,65590172-65702074,25-42,221412-256187,873499-1078482,118-154,68597355-68768392,102907-146478,4251706-4487069,64895-87330,8664371543-8664413195,4091-5065,537300-565631,77-115,83892238-83982935,6631446-6694349,1112-1649,7725-9776,1453397-1493799,10240-12328,15873-20410,1925-2744,4362535948-4362554186,3078725-3256936,710512-853550,279817-346202,45515-60928,3240-3952 diff --git a/aoc2025/input/day02_provided.txt b/aoc2025/input/day02_provided.txt deleted file mode 100644 index a3f22ef..0000000 --- a/aoc2025/input/day02_provided.txt +++ /dev/null @@ -1 +0,0 @@ -11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124 diff --git a/aoc2025/src/day02.rs b/aoc2025/src/day02.rs deleted file mode 100644 index 5b99438..0000000 --- a/aoc2025/src/day02.rs +++ /dev/null @@ -1,202 +0,0 @@ -use anyhow::{anyhow, Context, Result}; -use std::{fmt::Write, ops::RangeInclusive, str::FromStr}; - -const INPUT: &str = include_str!("../input/day02.txt"); - -pub fn run() -> Result { - let mut res = String::with_capacity(128); - writeln!(res, "part 1: {}", part1(INPUT)?)?; - writeln!(res, "part 2: {}", part2(INPUT)?)?; - Ok(res) -} - -struct IdRange(RangeInclusive); - -impl FromStr for IdRange { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - let (left, right) = s - .split_once('-') - .ok_or_else(|| anyhow!("couldn't find dash in range: `{}'", s))?; - let (left, right) = ( - left.parse() - .with_context(|| format!("couldn't parse left member of range: `{}'", left))?, - right - .trim() - .parse() - .with_context(|| format!("couldn't parse right member of range: `{}'", right))?, - ); - - Ok(IdRange(left..=right)) - } -} - -impl Iterator for IdRange { - type Item = as Iterator>::Item; - - fn next(&mut self) -> Option { - self.0.next() - } -} - -fn get_num_digits(num: &u64) -> usize { - let mut digits = 0; - let mut num = *num; - while num != 0 { - num /= 10; - digits += 1; - } - digits -} - -fn get_nth_digit(num: &u64, n: usize) -> u64 { - let mut num = *num; - for _ in 0..n { - num /= 10; - } - num % 10 -} - -fn is_repeated_twice(num: &u64) -> bool { - let num_digits = get_num_digits(num); - if !num_digits.is_multiple_of(2) { - return false; - } - let half = num_digits / 2; - - for (right, left) in (0..half).zip(half..num_digits) { - let ln = get_nth_digit(num, left); - let rn = get_nth_digit(num, right); - - if ln != rn { - return false; - } - } - - true -} - -fn part1(input: &str) -> Result { - let ranges = input - .split(',') - .map(IdRange::from_str) - .collect::>>()?; - - Ok(ranges - .into_iter() - .map(|range| range.filter(is_repeated_twice).sum::()) - .sum()) -} - -fn has_identical_chunks(num: &u64, chunk_size: usize) -> bool { - // build a "mask" for our chunk size - let mask = 10_u64.pow(chunk_size as u32); - - // this is what all chunks should look like to satisfy our condition - let target = *num % mask; - - let mut num = *num; - while num > target { - // shift num right by 10^(sub_digit_num) - num /= mask; - if num % mask != target { - return false; - } - } - - true -} - -fn is_repeated_at_least_twice(num: &u64) -> bool { - let num_digits = get_num_digits(num); - if num_digits < 2 { - return false; - } - - has_identical_chunks(num, 1) - || (2..=(num_digits / 2)).any(|n| { - // walk all possible divisors of our number of digits - if !num_digits.is_multiple_of(n) { - return false; - } - let chunk_size = num_digits / n; - has_identical_chunks(num, chunk_size) - }) -} - -fn part2(input: &str) -> Result { - let ranges = input - .split(',') - .map(IdRange::from_str) - .collect::>>()?; - - Ok(ranges - .into_iter() - .map(|range| range.filter(is_repeated_at_least_twice).sum::()) - .sum()) -} - -#[cfg(test)] -mod tests { - use super::*; - - const PROVIDED: &str = include_str!("../input/day02_provided.txt"); - - #[test] - fn repeated_twice() { - assert!(is_repeated_twice(&11)); - assert!(is_repeated_twice(&22)); - assert!(is_repeated_twice(&99)); - assert!(is_repeated_twice(&1010)); - assert!(is_repeated_twice(&1188511885)); - assert!(is_repeated_twice(&222222)); - assert!(is_repeated_twice(&446446)); - assert!(is_repeated_twice(&38593859)); - - assert!(!is_repeated_twice(&111)); - assert!(!is_repeated_twice(&121)); - assert!(!is_repeated_twice(&1)); - } - - #[test] - fn part1_provided() { - assert_eq!(part1(PROVIDED).unwrap(), 1227775554); - } - - #[test] - fn part1_real() { - assert_eq!(part1(INPUT).unwrap(), 26255179562); - } - - #[test] - fn repeated_at_least_twice() { - assert!(is_repeated_at_least_twice(&11)); - assert!(is_repeated_at_least_twice(&22)); - assert!(is_repeated_at_least_twice(&99)); - assert!(is_repeated_at_least_twice(&111)); - assert!(is_repeated_at_least_twice(&999)); - assert!(is_repeated_at_least_twice(&1010)); - assert!(is_repeated_at_least_twice(&1188511885)); - assert!(is_repeated_at_least_twice(&222222)); - assert!(is_repeated_at_least_twice(&446446)); - assert!(is_repeated_at_least_twice(&38593859)); - assert!(is_repeated_at_least_twice(&565656)); - assert!(is_repeated_at_least_twice(&824824824)); - assert!(is_repeated_at_least_twice(&2121212121)); - - assert!(!is_repeated_at_least_twice(&1121)); - assert!(!is_repeated_at_least_twice(&121)); - assert!(!is_repeated_at_least_twice(&1)); - } - - #[test] - fn part2_provided() { - assert_eq!(part2(PROVIDED).unwrap(), 4174379265); - } - - #[test] - fn part2_real() { - assert_eq!(part2(INPUT).unwrap(), 31680313976); - } -} diff --git a/aoc2025/src/lib.rs b/aoc2025/src/lib.rs index 28326d5..12b8f18 100644 --- a/aoc2025/src/lib.rs +++ b/aoc2025/src/lib.rs @@ -1,2 +1 @@ pub mod day01; -pub mod day02; diff --git a/aoc2025/src/main.rs b/aoc2025/src/main.rs index 1cb26fa..87fb660 100644 --- a/aoc2025/src/main.rs +++ b/aoc2025/src/main.rs @@ -3,10 +3,9 @@ use anyhow::Result; use aoc::DayFunc; use aoc2025::day01; -use aoc2025::day02; fn main() -> Result<()> { - let days: &[DayFunc] = &[day01::run, day02::run]; + let days: &[DayFunc] = &[day01::run]; aoc::run(days) }