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)
|
||||
}
|
||||
114
past-solutions/2-2.rs
Normal file
114
past-solutions/2-2.rs
Normal 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
3
rust-workspace/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
/target
|
||||
|
||||
.idea
|
||||
61
rust-workspace/Cargo.lock
generated
Normal file
61
rust-workspace/Cargo.lock
generated
Normal 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",
|
||||
]
|
||||
7
rust-workspace/Cargo.toml
Normal file
7
rust-workspace/Cargo.toml
Normal 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
1
rust-workspace/input.txt
Normal 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
114
rust-workspace/src/main.rs
Normal 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
|
||||
})
|
||||
}
|
||||
|
||||
1
rust-workspace/test_input.txt
Normal file
1
rust-workspace/test_input.txt
Normal 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
|
||||
Reference in New Issue
Block a user