generated from luke-else/AdventOfCodeXXXX
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
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:
@@ -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"] }
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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 {}),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user