more performance optimizations for 51

This commit is contained in:
Dr. Matthias Ratajczak
2022-08-16 18:59:17 +02:00
parent 2b86db2532
commit 799516005f
2 changed files with 68 additions and 19 deletions
+9 -3
View File
@@ -12,7 +12,7 @@ use num::ToPrimitive;
#[derive(Clone)] #[derive(Clone)]
pub struct Primes<T> { pub struct Primes<T> {
vector: Vec<T>, pub vector: Vec<T>,
set: HashSet<T>, set: HashSet<T>,
} }
@@ -157,14 +157,20 @@ mod test {
#[ignore] #[ignore]
#[test] #[test]
fn test_performance() { fn test_performance_1() {
let _ = Primes::get_between(100_000, 999_999);
}
#[ignore]
#[test]
fn test_performance_2() {
let primes = Primes::get_between(2, 10_000_000); let primes = Primes::get_between(2, 10_000_000);
assert_eq!(primes.len(), 664_579); assert_eq!(primes.len(), 664_579);
} }
#[ignore] #[ignore]
#[test] #[test]
fn test_performance_2() { fn test_performance_3() {
let primes = Primes::get_between(2, 1_000_000_000); let primes = Primes::get_between(2, 1_000_000_000);
assert_eq!(primes.len(), 50_847_534); assert_eq!(primes.len(), 50_847_534);
} }
+59 -16
View File
@@ -1,7 +1,7 @@
extern crate combination; extern crate combination;
extern crate primes; extern crate primes;
use std::process::exit; use std::{collections::HashSet, process::exit};
use combination::PositionCombinations; use combination::PositionCombinations;
use primes::Primes; use primes::Primes;
@@ -32,18 +32,26 @@ const DIGITS: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
fn main() { fn main() {
let all_primes = Primes::get_between(MIN_VALUE, MAX_VALUE); let all_primes = Primes::get_between(MIN_VALUE, MAX_VALUE);
let mut processed_cases = HashSet::new();
let mut primes_matching_pattern = Vec::with_capacity(TARGET_LENGTH);
for pattern in PositionCombinations::new(MIN_LENGTH, MAX_LENGTH, LENGTH) { for pattern in PositionCombinations::new(MIN_LENGTH, MAX_LENGTH, LENGTH) {
let mut primes_to_check = all_primes.clone(); for prime in &all_primes.vector {
primes_matching_pattern.clear();
while let Some(first) = primes_to_check.pop() { let digits = prime.to_digits();
let mut primes_matching_pattern = vec![];
let case = get_case_string(&digits, &pattern);
if processed_cases.contains(&case) {
continue;
} else {
processed_cases.insert(case.clone());
}
let digits = first.to_digits();
for digit in DIGITS { for digit in DIGITS {
let could_be_prime = let could_be_prime =
replace_digits_according_to_pattern_with_digit(&digits, digit, &pattern); replace_digits_with_new_digit_according_to_pattern(&digits, digit, &pattern);
if primes_to_check.contains(&could_be_prime) || could_be_prime == first { if all_primes.contains(&could_be_prime) {
primes_matching_pattern.push(could_be_prime); primes_matching_pattern.push(could_be_prime);
} }
} }
@@ -55,7 +63,15 @@ fn main() {
} }
} }
fn replace_digits_according_to_pattern_with_digit( fn get_case_string(digits: &[u8], pattern: &[bool]) -> String {
digits
.iter()
.zip(pattern)
.map(|(d, b)| if *b { '*' } else { *d as char })
.collect()
}
fn replace_digits_with_new_digit_according_to_pattern(
prime_as_digits: &[u8], prime_as_digits: &[u8],
new_digit: u8, new_digit: u8,
pattern: &[bool], pattern: &[bool],
@@ -86,24 +102,36 @@ trait ToDigits {
#[allow(clippy::needless_range_loop)] #[allow(clippy::needless_range_loop)]
impl ToDigits for Int { impl ToDigits for Int {
fn to_digits(&self) -> Vec<u8> { fn to_digits(&self) -> Vec<u8> {
let oom = (*self as f64).log10().floor() as i32; let oom = get_order_of_magnitude(*self);
let length = oom as usize + 1; let length = oom as usize;
let mut var = *self; let mut var = *self;
let mut result = vec![0; length]; let mut result = vec![0; length];
for i in 0..length as usize { for i in 0..length {
let power = 10_f64.powi(oom - i as i32); let power = 10_u64.pow(oom - i as u32 - 1);
let digit = (var as f64 / power).floor(); let digit = var / power;
var -= (digit * power) as Int; var -= (digit * power) as Int;
result[i] = digit as u8; result[i] = digit as u8;
} }
assert_eq!(var, 0); debug_assert_eq!(var, 0);
result result
} }
} }
fn get_order_of_magnitude(x: Int) -> u32 {
let mut tmp = 1;
let mut oom = 1;
while tmp - 1 < x {
oom += 1;
tmp *= 10;
}
oom - 1
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{replace_digits_according_to_pattern_with_digit, ToDigits}; use crate::{
get_order_of_magnitude, replace_digits_with_new_digit_according_to_pattern, ToDigits,
};
#[test] #[test]
fn test_num_to_digits() { fn test_num_to_digits() {
@@ -117,7 +145,11 @@ mod test {
let new_digit = 0; let new_digit = 0;
let pattern = [false, true, true, true, false, false]; let pattern = [false, true, true, true, false, false];
assert_eq!( assert_eq!(
replace_digits_according_to_pattern_with_digit(&prime_as_digits, new_digit, &pattern), replace_digits_with_new_digit_according_to_pattern(
&prime_as_digits,
new_digit,
&pattern
),
500_021 500_021
); );
} }
@@ -127,4 +159,15 @@ mod test {
let num = 37871_u64; let num = 37871_u64;
assert_eq!(vec![3, 7, 8, 7, 1], num.to_digits()); assert_eq!(vec![3, 7, 8, 7, 1], num.to_digits());
} }
#[test]
fn test_oom() {
assert_eq!(get_order_of_magnitude(3), 1);
assert_eq!(get_order_of_magnitude(9), 1);
assert_eq!(get_order_of_magnitude(10), 2);
assert_eq!(get_order_of_magnitude(32), 2);
assert_eq!(get_order_of_magnitude(10_000), 5);
assert_eq!(get_order_of_magnitude(10_001), 5);
assert_eq!(get_order_of_magnitude(37_871), 5);
}
} }