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

114
past-solutions/2-2.rs Normal file
View File

@@ -0,0 +1,114 @@
use std::collections::HashSet;
use std::io::Read;
use std::iter;
use std::num::{NonZero, NonZeroU32, NonZeroU64};
use rayon::prelude::*;
fn main() {
let mut problem = parse_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);
let count = problem.ranges.par_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 = lowest_of_degree(digitCountU);
return vec![(*lower, lowestOfDegree-1, digitCountL), (lowestOfDegree, *upper, digitCountU)];
}).flatten().collect::<Vec<_>>();
return CleanedProblem{ranges: new_ranges};
}
fn lowest_of_degree(degree : NonZeroU32) -> u64{
10u64.pow(degree.get() - 1)
}
fn compute_range(lower_bound: u64, upper_bound: u64) -> u64 {
let digitCount = count_digits(lower_bound);
(lower_bound..=upper_bound).map(|i|{
if is_combination(i) {
Some(i)
}else{
None
}
}).flatten().sum()
}
fn count_digits(mut n : u64) -> NonZeroU32{
let mut count = 0u64;
while (n != 0){
n = n / 10;
count +=1 ;
}
return unsafe{NonZeroU32::new_unchecked(count as u32)};
}
fn is_combination(n: u64) -> bool {
let digit_count = count_digits(n).get();
(1..=digit_count)
.filter(|count| digit_count % count == 0)
.filter(|count| *count <= digit_count/ 2)
.any(|count| {
let mask = 10u64.pow(count as u32);
let block = n % mask;
let mut x = n;
while x > 0 {
if x % mask != block {
return false;
}
x /= mask;
}
true
})
}