finish 51

This commit is contained in:
timeshifter
2022-08-14 21:00:18 +02:00
parent 5b5c77d5b4
commit 4bac3290e5
4 changed files with 184 additions and 64 deletions
+40 -12
View File
@@ -1,5 +1,6 @@
struct PositionCombinations { pub struct PositionCombinations {
min_length: usize, min_length: usize,
max_length: usize,
state: Vec<bool>, state: Vec<bool>,
finished: bool, finished: bool,
} }
@@ -8,13 +9,14 @@ impl Iterator for PositionCombinations {
type Item = Vec<bool>; type Item = Vec<bool>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
loop { loop {
let result = self.state.clone(); let result = self.state.clone();
self.increment(); self.increment();
if result.iter().filter(|x| **x).count() >= self.min_length { if self.finished {
return None;
}
if (self.min_length..=self.max_length).contains(&result.iter().filter(|x| **x).count())
{
return Some(result); return Some(result);
} }
} }
@@ -22,11 +24,12 @@ impl Iterator for PositionCombinations {
} }
impl PositionCombinations { impl PositionCombinations {
fn new(min_length: usize, max_length: usize) -> Self { pub fn new(min_length: usize, max_length: usize, length: usize) -> Self {
let state = vec![false; max_length]; let state = vec![false; length];
let finished = false; let finished = false;
Self { Self {
min_length, min_length,
max_length,
state, state,
finished, finished,
} }
@@ -46,15 +49,25 @@ impl PositionCombinations {
} }
} }
pub trait ToString {
fn to_string(&self) -> String;
}
impl ToString for Vec<bool> {
fn to_string(&self) -> String {
self.iter().map(|b| if *b { 'x' } else { '.' }).collect()
}
}
#[cfg(test)] #[cfg(test)]
mod test { mod test {
#[test]
fn test_combination() {
use crate::combination::PositionCombinations; use crate::combination::PositionCombinations;
use std::collections::HashSet; use std::collections::HashSet;
let combinator = PositionCombinations::new(2, 4); #[test]
let result: HashSet<_> = combinator.into_iter().collect(); fn test_combination_2_3_4() {
let combinator = PositionCombinations::new(2, 3, 4);
let result: Vec<_> = combinator.into_iter().collect();
let mut number_solutions = result.len(); let mut number_solutions = result.len();
let mut solution = HashSet::new(); let mut solution = HashSet::new();
solution.insert(vec![false, false, true, true]); solution.insert(vec![false, false, true, true]);
@@ -67,7 +80,22 @@ mod test {
solution.insert(vec![true, false, true, true]); solution.insert(vec![true, false, true, true]);
solution.insert(vec![true, true, false, true]); solution.insert(vec![true, true, false, true]);
solution.insert(vec![true, true, true, false]); solution.insert(vec![true, true, true, false]);
solution.insert(vec![true, true, true, true]); for item in solution {
assert!(result.contains(&item));
number_solutions -= 1;
}
assert_eq!(number_solutions, 0);
}
#[test]
fn test_combination_2_2_3() {
let combinator = PositionCombinations::new(2, 2, 3);
let result: Vec<_> = combinator.into_iter().collect();
let mut number_solutions = result.len();
let mut solution = HashSet::new();
solution.insert(vec![false, true, true]);
solution.insert(vec![true, false, true]);
solution.insert(vec![true, true, false]);
for item in solution { for item in solution {
assert!(result.contains(&item)); assert!(result.contains(&item));
number_solutions -= 1; number_solutions -= 1;
+3
View File
@@ -0,0 +1,3 @@
macro_rules! dbg_println {
($($arg:tt)*) => (#[cfg(debug_assertions)] println!($($arg)*));
}
+96 -42
View File
@@ -1,79 +1,133 @@
mod combination; mod combination;
mod primes; mod primes;
#[macro_use]
mod macros;
use crate::combination::{PositionCombinations, ToString};
use crate::primes::Primes; use crate::primes::Primes;
type Int = i64; type Int = u64;
const MIN_VALUE: Int = 10_000; // EXAMPLE 1
const MAX_VALUE: Int = 99_999; // const MIN_VALUE: Int = 10;
// const MAX_VALUE: Int = 99;
// const LENGTH: usize = 2;
// const MIN_LENGTH: usize = 1;
const DIGITS: [Int; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; // OWN TEST
// const MIN_VALUE: Int = 10_000_000; // const MIN_VALUE: Int = 100;
// const MAX_VALUE: Int = 10_010_000; // const MAX_VALUE: Int = 999;
// const MAX_VALUE: Int = 99_999_999; // const LENGTH: usize = 3;
// const LENGTH_OF_NUMBERS: usize = 5;
// const MIN_LENGTH: usize = 2; // const MIN_LENGTH: usize = 2;
// EXAMPLE 2
// const MIN_VALUE: Int = 10_000;
// const MAX_VALUE: Int = 99_999;
// const LENGTH: usize = 5;
// const MIN_LENGTH: usize = 2;
// FINAL
const MIN_VALUE: Int = 100_000;
const MAX_VALUE: Int = 999_999;
const LENGTH: usize = 6;
const MIN_LENGTH: usize = 2;
const MAX_LENGTH: usize = LENGTH - 1;
const DIGITS: [u8; 10] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
fn main() { fn main() {
let primes = Primes::get_between(MIN_VALUE, MAX_VALUE); let all_primes = Primes::get_between(MIN_VALUE, MAX_VALUE);
// let mut new_primes = primes.clone(); let mut best_of_all_combinations = vec![];
for p in primes.vector.iter() { for pattern in PositionCombinations::new(MIN_LENGTH, MAX_LENGTH, LENGTH) {
let mut candidates = vec![]; dbg_println!("{}", pattern.to_string());
let digits = num_to_digits(p); let mut best_this_combination = vec![];
for d in DIGITS { let mut primes_to_check = all_primes.clone();
let mut these_digits = digits.clone(); while let Some(first) = primes_to_check.pop() {
these_digits[3] = d; let mut primes_matching_pattern = vec![];
these_digits[4] = d; let digits = first.to_digits();
let num = digits_to_num(these_digits); for digit in DIGITS {
if primes.set.contains(&num) { let could_be_prime = digits
candidates.push(num) .iter()
.zip(pattern.clone())
.map(|(d, b)| if b { digit } else { *d })
.collect::<Vec<u8>>()
.to_num();
if primes_to_check.contains(&could_be_prime) || could_be_prime == first {
primes_matching_pattern.push(could_be_prime);
} }
} }
if candidates.len() > 4 { if primes_matching_pattern.len() > 2 {
println!("candidates"); best_this_combination.push(primes_matching_pattern)
for c in &candidates {
// new_primes.remove(c);
println!("{c}");
} }
} }
if !best_this_combination.is_empty() {
best_of_all_combinations.push(get_longest(best_this_combination, false));
} }
// println!("new primes"); }
// for p in new_primes.vector.iter() { println!("{:#?}", get_longest(best_of_all_combinations, false));
// println!("{p}");
// }
}
fn num_to_digits(n: &Int) -> Vec<Int> {
n.to_string()
.chars()
.map(|x| x.to_digit(10).unwrap() as Int)
.collect()
} }
fn digits_to_num(vec: Vec<Int>) -> Int { fn get_longest(mut vec: Vec<Vec<Int>>, print: bool) -> Vec<Int> {
if vec.is_empty() {
panic!("cannot give the longest element of an empty vector")
}
if print {
println!("{:#?}", vec);
}
vec.sort_by_key(|c| c.len());
let length = vec.last().unwrap().len();
vec.into_iter().find(|v| v.len() == length).unwrap()
}
impl ToString for Vec<u8> {
fn to_string(&self) -> String {
self.iter().map(|d| d.to_string()).collect()
}
}
trait ToDigits {
fn to_digits(&self) -> Vec<u8>;
}
trait ToNum {
fn to_num(&self) -> Int;
}
impl ToDigits for Int {
fn to_digits(&self) -> Vec<u8> {
self.to_string()
.chars()
.map(|x| x.to_digit(10).unwrap() as u8)
.collect()
}
}
impl ToNum for Vec<u8> {
fn to_num(&self) -> Int {
let mut result = 0; let mut result = 0;
let mut position = 1; let mut position = 1;
for digit in vec.iter().rev() { for digit in self.iter().rev() {
result += digit * position; result += *digit as Int * position;
position *= 10; position *= 10;
} }
result result
}
} }
#[cfg(test)] #[cfg(test)]
mod test { mod test {
use crate::{digits_to_num, num_to_digits}; use crate::{ToDigits, ToNum};
#[test] #[test]
fn test_digits_to_num() { fn test_digits_to_num() {
let digits = vec![5, 7, 3, 8, 1]; let digits = vec![5, 7, 3, 8, 1];
assert_eq!(digits_to_num(digits), 57381); assert_eq!(digits.to_num(), 57381);
} }
#[test] #[test]
fn test_num_to_digits() { fn test_num_to_digits() {
let num = 83371; let num = 83371;
assert_eq!(num_to_digits(&num), vec![8, 3, 3, 7, 1]); assert_eq!(num.to_digits(), vec![8, 3, 3, 7, 1]);
} }
} }
+38 -3
View File
@@ -7,9 +7,9 @@ use std::collections::HashSet;
use std::hash::Hash; use std::hash::Hash;
#[derive(Clone)] #[derive(Clone)]
pub struct Primes<T: Num + ToPrimitive> { pub struct Primes<T> {
pub vector: Vec<T>, vector: Vec<T>,
pub set: HashSet<T>, set: HashSet<T>,
} }
impl<T> Primes<T> impl<T> Primes<T>
@@ -38,6 +38,7 @@ where
set.insert(prime); set.insert(prime);
} }
} }
vector.reverse(); // so that self.pop removes the smallest prime
Primes { vector, set } Primes { vector, set }
} }
@@ -70,6 +71,23 @@ where
self.set.remove(num); self.set.remove(num);
}; };
} }
// pub fn len(&self) -> usize {
// debug_assert_eq!(self.vector.len(), self.set.len());
// self.vector.len()
// }
pub fn pop(&mut self) -> Option<T> {
let result = self.vector.pop();
if let Some(value) = result {
self.set.remove(&value);
}
result
}
pub fn contains(&self, val: &T) -> bool {
self.set.contains(val)
}
} }
#[cfg(test)] #[cfg(test)]
@@ -80,6 +98,23 @@ mod test {
fn test_example_prime() { fn test_example_prime() {
let primes = Primes::get_between(2, 99_999); let primes = Primes::get_between(2, 99_999);
assert!(primes.set.contains(&56003)); assert!(primes.set.contains(&56003));
assert!(primes.set.contains(&56993));
assert!(!primes.set.contains(&56002)); assert!(!primes.set.contains(&56002));
} }
#[test]
fn test_remove() {
let mut primes = Primes::get_between(2, 9);
assert!(primes.contains(&7));
primes.remove(&7);
assert!(!primes.contains(&7));
}
#[test]
fn test_pop() {
let mut primes = Primes::get_between(10, 20);
assert!(primes.contains(&11));
primes.pop();
assert!(!primes.contains(&11));
}
} }