This commit is contained in:
2025-12-02 18:45:40 +01:00
commit e8fb670ee5
8 changed files with 421 additions and 0 deletions

120
past-solutions/2-1.rs Normal file
View File

@@ -0,0 +1,120 @@
use std::io::Read;
use std::iter;
use std::num::{NonZero, NonZeroU32};
fn main() {
let mut problem = parse_problem();
println!("Parsed problem: {:?}", problem);
println!("Count in total: {}", compute_problem(&mut problem))
}
#[derive(Debug)]
struct Problem{
ranges: Vec<(u64, u64)>
}
#[derive(Debug)]
struct CleanedProblem{
ranges: Vec<(u64, u64, NonZeroU32)>
}
fn parse_problem() -> Problem {
let mut input = String::new();
std::io::stdin().read_to_string(&mut input).expect("Failed to read input");
let ranges = input.split(',').
map(|x| x.split_once('-').expect("dash in there"))
.map(|x| (x.0.parse::<u64>().expect("Parse error on 0"), x.1.parse::<u64>().expect("Parse error on 1")))
.collect::<Vec<_>>();
return Problem{
ranges,
};
}
fn compute_problem(problem: &mut Problem) -> u64 {
//Potentialy ensure it is not overlapping
let problem = clean_problem(problem);
println!("Cleaned problem: {:?}", problem);
let count = problem.ranges.iter().map(|range| compute_range(range.0, range.1)).sum::<u64>();
return count;
}
fn clean_problem(problem: &Problem) -> CleanedProblem {
let new_ranges = problem.ranges.iter().map(|(lower, upper)|{
if (upper < lower){
return vec![]
}
let digitCountU = count_digits(*upper);
let digitCountL = count_digits(*lower);
if (digitCountL == digitCountU){
return vec![(*lower, *upper, digitCountU)];
}
let lowestOfDegree = lowestOfDegree(digitCountU);
return vec![(*lower, lowestOfDegree-1, digitCountL), (lowestOfDegree, *upper, digitCountU)];
}).flatten().collect::<Vec<_>>();
return CleanedProblem{ranges: new_ranges};
}
fn lowestOfDegree(degree : NonZeroU32) -> u64{
10u64.pow(degree.get() - 1)
}
fn compute_range(lower_bound: u64, upper_bound: u64) -> u64 {
assert!(lower_bound > 0 && upper_bound > 0);
assert!(upper_bound > lower_bound);
assert!(count_digits(upper_bound) == count_digits(lower_bound));
let digitCount = count_digits(upper_bound);
if digitCount.get() % 2 != 0{
return 0;
}
let halfDigitCount = NonZeroU32::new(digitCount.get() / 2).unwrap();
let mut half = (lower_bound / 10u64.pow(halfDigitCount.get())).min(lower_bound % 10u64.pow(halfDigitCount.get()));
let mut count = 0;
loop{
let whole = combine_numbers(half, halfDigitCount);
if whole >= lower_bound && whole <= upper_bound{
count += whole;
}else if whole > upper_bound{
break;
}
half += 1;
}
return count;
}
fn count_digits(mut n : u64) -> NonZeroU32{
assert!(n > 0);
let mut count = 0u64;
while (n != 0){
n = n / 10;
count +=1 ;
}
return unsafe{NonZeroU32::new_unchecked(count as u32)};
}
fn combine_numbers(half : u64, degree : NonZeroU32) -> u64 {
return half + half * 10u64.pow(degree.get() as u32)
}