diff --git a/src/day2.rs b/src/day2.rs index 75ce09f..d5629c6 100644 --- a/src/day2.rs +++ b/src/day2.rs @@ -2,6 +2,19 @@ use aoc_runner_derive::{aoc, aoc_generator}; use itertools::Itertools; use std::ops::RangeInclusive; +const POW10MAX: usize = u64::MAX.ilog10() as usize; +const POW10: [u64; POW10MAX] = pow10_lut(); + +const fn pow10_lut() -> [u64; N] { + let mut res = [0; N]; + let mut i = 0; + while i < N { + res[i] = 10u64.pow(i as u32); + i += 1; + } + res +} + #[aoc_generator(day2)] fn parse(input: &str) -> Vec> { input @@ -62,12 +75,12 @@ fn part1_arithmetic_brute(input: &[RangeInclusive]) -> u64 { for r in input { // println!("Range: {:?}", r); for product in r.clone() { - let n_digits = product.ilog10() + 1; + let n_digits = (product.ilog10() + 1) as usize; if n_digits % 2 != 0 { continue; } - let decade = 10u64.pow(n_digits / 2); + let decade = POW10[n_digits / 2]; let lhs = product / decade; let rhs = product % decade; // println!("{product} {n_digits}: D:{decade} L:{lhs} R:{rhs}"); @@ -84,21 +97,19 @@ fn part2_arithmetic_brute(input: &[RangeInclusive]) -> u64 { let mut invalid_sum = 0; for r in input { for product in r.clone() { - let n_digits = product.ilog10() + 1; + let n_digits = (product.ilog10() + 1) as usize; for n in 1..=n_digits / 2 { let repetitions = n_digits / n; if n_digits % n != 0 { continue; } - let decade = 10u64.pow(n_digits - n); + let decade = POW10[n_digits - n]; let lhs = product / decade; let remainder = product % decade; // for each repetition we multiply by 10^(rep * n) - let expected_remainder = (0..repetitions - 1) - .map(|rep| lhs * 10u64.pow(rep * n)) - .sum(); + let expected_remainder = (0..repetitions - 1).map(|rep| lhs * POW10[rep * n]).sum(); if remainder == expected_remainder { invalid_sum += product; @@ -114,19 +125,19 @@ fn part2_arithmetic_brute(input: &[RangeInclusive]) -> u64 { fn part1_clever(input: &[RangeInclusive]) -> u64 { let mut invalid_sum = 0; for r in input { - let n_digits = r.start().ilog10() + 1; + let n_digits = (r.start().ilog10() + 1) as usize; let mut lhs = if n_digits % 2 != 0 { // If the number of digits is odd, we start our guess at the first possibility in the next decade - 10u64.pow(n_digits / 2) + POW10[n_digits / 2] } else { - let start_decade = 10u64.pow(n_digits / 2); + let start_decade = POW10[n_digits / 2]; r.start() / start_decade }; // we will guess the next repeater, and check if it's in range, if not we are done. loop { - let repeater = lhs * 10u64.pow(lhs.ilog10() + 1) + lhs; + let repeater = lhs * POW10[(lhs.ilog10() + 1) as usize] + lhs; if repeater < *r.start() { lhs += 1 } else if r.contains(&repeater) {