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)
}

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
})
}

3
rust-workspace/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
/target
.idea

61
rust-workspace/Cargo.lock generated Normal file
View File

@@ -0,0 +1,61 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "crossbeam-deque"
version = "0.8.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
dependencies = [
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
[[package]]
name = "either"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
[[package]]
name = "rayon"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
dependencies = [
"either",
"rayon-core",
]
[[package]]
name = "rayon-core"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
dependencies = [
"crossbeam-deque",
"crossbeam-utils",
]
[[package]]
name = "rust-workspace"
version = "0.1.0"
dependencies = [
"rayon",
]

View File

@@ -0,0 +1,7 @@
[package]
name = "rust-workspace"
version = "0.1.0"
edition = "2024"
[dependencies]
rayon = "1.11.0"

1
rust-workspace/input.txt Normal file
View File

@@ -0,0 +1 @@
9595822750-9596086139,1957-2424,88663-137581,48152-65638,12354817-12385558,435647-489419,518494-609540,2459-3699,646671-688518,195-245,295420-352048,346-514,8686839668-8686892985,51798991-51835611,8766267-8977105,2-17,967351-995831,6184891-6331321,6161577722-6161678622,912862710-913019953,6550936-6625232,4767634976-4767662856,2122995-2257010,1194-1754,779-1160,22-38,4961-6948,39-53,102-120,169741-245433,92902394-92956787,531-721,64-101,15596-20965,774184-943987,8395-11781,30178-47948,94338815-94398813

114
rust-workspace/src/main.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
})
}

View File

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