feat: Completed day 2code .
Some checks failed
Continuous integration / Check (push) Successful in 44s
Continuous integration / Test Suite (push) Successful in 44s
Continuous integration / Rustfmt (push) Successful in 31s
Continuous integration / Clippy (push) Failing after 44s
Continuous integration / build (push) Successful in 44s

This commit is contained in:
2025-12-02 10:24:07 +00:00
parent 244314a2f0
commit 0dee050ef2
7 changed files with 226 additions and 10 deletions

View File

@@ -4,4 +4,7 @@ version = "0.1.0"
edition = "2024"
[dependencies]
num-bigint = "0.4.6"
num-integer = "0.1.46"
num-traits = "0.2.19"
tokio = { version = "1.48.0", features = ["full"] }

View File

@@ -0,0 +1 @@
492410748-492568208,246-390,49-90,16-33,142410-276301,54304-107961,12792-24543,3434259704-3434457648,848156-886303,152-223,1303-1870,8400386-8519049,89742532-89811632,535853-567216,6608885-6724046,1985013826-1985207678,585591-731454,1-13,12067202-12233567,6533-10235,6259999-6321337,908315-972306,831-1296,406-824,769293-785465,3862-5652,26439-45395,95-136,747698990-747770821,984992-1022864,34-47,360832-469125,277865-333851,2281-3344,2841977-2953689,29330524-29523460

View File

@@ -0,0 +1,3 @@
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,
1698522-1698528,446443-446449,38593856-38593862,565653-565659,
824824821-824824827,2121212118-2121212124

View File

@@ -0,0 +1,3 @@
11-22,95-115,998-1012,1188511880-1188511890,222220-222224,
1698522-1698528,446443-446449,38593856-38593862,565653-565659,
824824821-824824827,2121212118-2121212124

View File

@@ -13,7 +13,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
/* Uncomment these before the start of each day! */
let days: Vec<Box<dyn Solution>> = vec![
Box::new(day01::Day01 {}),
// Box::new(day02::Day02 {}),
Box::new(day02::Day02 {}),
// Box::new(day03::Day03 {}),
// Box::new(day04::Day04 {}),
// Box::new(day05::Day05 {}),

View File

@@ -25,7 +25,7 @@ impl Solution for Day01 {
impl Day01 {
fn count_zeros(input: &Vec<String>, count_passing: bool) -> usize {
// Dial starts at 50
let mut pos: i64 = 50;
let mut pos: i32 = 50;
let mut zeros: usize = 0;
for line in input {
@@ -37,7 +37,7 @@ impl Day01 {
let mut chars = line.chars();
let dir = chars.next().expect("empty line");
let dist_str: String = chars.collect::<String>().trim().to_string();
let dist: i64 = dist_str.parse().expect("invalid distance number");
let dist: i32 = dist_str.parse().expect("invalid distance number");
// Count any time that the dial moves past 0.
if count_passing {

View File

@@ -1,20 +1,191 @@
use super::Solution;
use num_bigint::BigUint;
use num_integer::Integer;
use num_traits::{One, Zero};
use std::collections::HashSet;
pub struct Day02 {}
impl Solution for Day02 {
fn part1(
&self,
_input: &mut Vec<String>,
input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
Ok(Box::new("Ready"))
let s = input.join("\n");
let ranges = self.parse_ranges(s.as_str());
// Determine maximum digits among all upper bounds
let overall_max = ranges
.iter()
.map(|(_, hi)| hi.clone())
.max()
.unwrap_or_else(|| BigUint::zero());
let max_digits = self.digits_of(&overall_max);
// Precompute 10^n for n up to max_digits
let mut pow10_cache: Vec<BigUint> = Vec::with_capacity(max_digits + 1);
for i in 0..=max_digits {
pow10_cache.push(self.pow10(i));
}
let mut total = BigUint::zero();
// For PART 1:
// Invalid number is exactly two blocks: x repeated twice.
// If x has k digits, the total has length 2k.
// Value = x * (10^k + 1)
for k in 1..=max_digits / 2 {
let pow10k = &pow10_cache[k];
// x ranges: k-digit numbers with no leading zero.
let x_min = if k == 1 {
BigUint::one()
} else {
pow10_cache[k - 1].clone()
};
let x_max = pow10k - BigUint::one();
// multiplier = 10^k + 1
let multiplier = pow10k + BigUint::one();
for (lo, hi) in &ranges {
if lo > hi {
continue;
}
// Compute ceil(lo / multiplier)
let x_low = {
let (q, r) = lo.div_rem(&multiplier);
if r.is_zero() { q } else { q + BigUint::one() }
};
// Compute floor(hi / multiplier)
let x_high = hi / &multiplier;
// Intersect x range with [x_min, x_max]
let a = if x_low < x_min { x_min.clone() } else { x_low };
let b = if x_high > x_max {
x_max.clone()
} else {
x_high
};
if a > b {
continue;
}
// count n = b - a + 1
let n = &b - &a + BigUint::one();
// sum_x = n*(a+b)/2
let ab = &a + &b;
let prod = &n * ab;
let sum_x = prod / 2u32;
// Add multiplier * sum_x
total += &multiplier * sum_x;
}
}
Ok(Box::new(total))
}
fn part2(
&self,
_input: &mut Vec<String>,
input: &mut Vec<String>,
) -> Result<Box<dyn std::fmt::Display>, Box<dyn std::error::Error>> {
Ok(Box::new("Ready"))
let s = input.join("\n");
let ranges = self.parse_ranges(s.as_str());
// Compute limits
let overall_max = ranges
.iter()
.map(|(_, hi)| hi.clone())
.max()
.unwrap_or_else(|| BigUint::zero());
let max_digits = self.digits_of(&overall_max);
// Precompute powers of 10
let mut pow10_cache = Vec::with_capacity(max_digits + 1);
for i in 0..=max_digits {
pow10_cache.push(self.pow10(i));
}
// The important fix: ALWAYS DEDUP
let mut invalid_ids = HashSet::<BigUint>::new();
// Consider total length L
for l in 2..=max_digits {
for k in 1..=l {
if l % k != 0 {
continue;
}
let r = l / k;
if r < 2 {
continue;
}
let pow10k = &pow10_cache[k];
let pow10l = &pow10_cache[l];
// Repetition multiplier: 111... (r groups of size k)
let numerator = pow10l - BigUint::one();
let denom = pow10k - BigUint::one();
if denom.is_zero() {
continue;
}
let multiplier = &numerator / &denom;
// k-digit block roots
let x_min = if k == 1 {
BigUint::one()
} else {
pow10_cache[k - 1].clone()
};
let x_max = pow10k - BigUint::one();
for (lo, hi) in &ranges {
if lo > hi {
continue;
}
let x_low = {
let (q, rmd) = lo.div_rem(&multiplier);
if rmd.is_zero() { q } else { q + BigUint::one() }
};
let x_high = hi / &multiplier;
let a = if x_low < x_min { x_min.clone() } else { x_low };
let b = if x_high > x_max {
x_max.clone()
} else {
x_high
};
if a > b {
continue;
}
// Enumerate all x in [a, b] — this is small in practice
let mut x = a;
while x <= b {
let id = &x * &multiplier;
invalid_ids.insert(id);
x += BigUint::one();
}
}
}
}
// Sum final unique invalid IDs
let mut total = BigUint::zero();
for id in invalid_ids {
total += id;
}
Ok(Box::new(total))
}
fn get_day(&self) -> u8 {
@@ -22,7 +193,42 @@ impl Solution for Day02 {
}
}
impl Day02 {}
impl Day02 {
fn pow10(&self, n: usize) -> BigUint {
let ten = BigUint::from(10u8);
ten.pow(n as u32)
}
fn digits_of(&self, n: &BigUint) -> usize {
if n.is_zero() {
return 1;
}
n.to_string().len()
}
fn parse_ranges(&self, s: &str) -> Vec<(BigUint, BigUint)> {
let mut out = Vec::new();
for token in s.split(',') {
let t = token.trim();
if t.is_empty() {
continue;
}
let parts: Vec<&str> = t.split('-').collect();
if parts.len() != 2 {
eprintln!("Skipping malformed token: {}", t);
continue;
}
let a = parts[0].trim().parse::<BigUint>().expect("parse start");
let b = parts[1].trim().parse::<BigUint>().expect("parse end");
if a <= b {
out.push((a, b));
} else {
out.push((b, a));
}
}
out
}
}
/// Test from puzzle input
#[cfg(test)]
@@ -44,7 +250,7 @@ mod test {
.unwrap()
.to_string();
assert_eq!(answer, "Ready");
assert_eq!(answer, "1227775554");
}
#[test]
@@ -61,6 +267,6 @@ mod test {
.unwrap()
.to_string();
assert_eq!(answer, "Ready");
assert_eq!(answer, "4174379265");
}
}