day 2
This commit is contained in:
120
past-solutions/2-1.rs
Normal file
120
past-solutions/2-1.rs
Normal 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)
|
||||
}
|
||||
Reference in New Issue
Block a user