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
+42 -14
View File
@@ -1,5 +1,6 @@
struct PositionCombinations {
pub struct PositionCombinations {
min_length: usize,
max_length: usize,
state: Vec<bool>,
finished: bool,
}
@@ -8,13 +9,14 @@ impl Iterator for PositionCombinations {
type Item = Vec<bool>;
fn next(&mut self) -> Option<Self::Item> {
if self.finished {
return None;
}
loop {
let result = self.state.clone();
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);
}
}
@@ -22,11 +24,12 @@ impl Iterator for PositionCombinations {
}
impl PositionCombinations {
fn new(min_length: usize, max_length: usize) -> Self {
let state = vec![false; max_length];
pub fn new(min_length: usize, max_length: usize, length: usize) -> Self {
let state = vec![false; length];
let finished = false;
Self {
min_length,
max_length,
state,
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)]
mod test {
#[test]
fn test_combination() {
use crate::combination::PositionCombinations;
use std::collections::HashSet;
use crate::combination::PositionCombinations;
use std::collections::HashSet;
let combinator = PositionCombinations::new(2, 4);
let result: HashSet<_> = combinator.into_iter().collect();
#[test]
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 solution = HashSet::new();
solution.insert(vec![false, false, true, true]);
@@ -67,7 +80,22 @@ mod test {
solution.insert(vec![true, false, true, true]);
solution.insert(vec![true, true, false, true]);
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 {
assert!(result.contains(&item));
number_solutions -= 1;
+3
View File
@@ -0,0 +1,3 @@
macro_rules! dbg_println {
($($arg:tt)*) => (#[cfg(debug_assertions)] println!($($arg)*));
}
+101 -47
View File
@@ -1,79 +1,133 @@
mod combination;
mod primes;
#[macro_use]
mod macros;
use crate::combination::{PositionCombinations, ToString};
use crate::primes::Primes;
type Int = i64;
type Int = u64;
const MIN_VALUE: Int = 10_000;
const MAX_VALUE: Int = 99_999;
// EXAMPLE 1
// 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];
// const MIN_VALUE: Int = 10_000_000;
// const MAX_VALUE: Int = 10_010_000;
// const MAX_VALUE: Int = 99_999_999;
// const LENGTH_OF_NUMBERS: usize = 5;
// OWN TEST
// const MIN_VALUE: Int = 100;
// const MAX_VALUE: Int = 999;
// const LENGTH: usize = 3;
// 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() {
let primes = Primes::get_between(MIN_VALUE, MAX_VALUE);
// let mut new_primes = primes.clone();
for p in primes.vector.iter() {
let mut candidates = vec![];
let digits = num_to_digits(p);
for d in DIGITS {
let mut these_digits = digits.clone();
these_digits[3] = d;
these_digits[4] = d;
let num = digits_to_num(these_digits);
if primes.set.contains(&num) {
candidates.push(num)
let all_primes = Primes::get_between(MIN_VALUE, MAX_VALUE);
let mut best_of_all_combinations = vec![];
for pattern in PositionCombinations::new(MIN_LENGTH, MAX_LENGTH, LENGTH) {
dbg_println!("{}", pattern.to_string());
let mut best_this_combination = vec![];
let mut primes_to_check = all_primes.clone();
while let Some(first) = primes_to_check.pop() {
let mut primes_matching_pattern = vec![];
let digits = first.to_digits();
for digit in DIGITS {
let could_be_prime = digits
.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 primes_matching_pattern.len() > 2 {
best_this_combination.push(primes_matching_pattern)
}
}
if candidates.len() > 4 {
println!("candidates");
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!("{p}");
// }
}
fn num_to_digits(n: &Int) -> Vec<Int> {
n.to_string()
.chars()
.map(|x| x.to_digit(10).unwrap() as Int)
.collect()
println!("{:#?}", get_longest(best_of_all_combinations, false));
}
fn digits_to_num(vec: Vec<Int>) -> Int {
let mut result = 0;
let mut position = 1;
for digit in vec.iter().rev() {
result += digit * position;
position *= 10;
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 position = 1;
for digit in self.iter().rev() {
result += *digit as Int * position;
position *= 10;
}
result
}
result
}
#[cfg(test)]
mod test {
use crate::{digits_to_num, num_to_digits};
use crate::{ToDigits, ToNum};
#[test]
fn test_digits_to_num() {
let digits = vec![5, 7, 3, 8, 1];
assert_eq!(digits_to_num(digits), 57381);
assert_eq!(digits.to_num(), 57381);
}
#[test]
fn test_num_to_digits() {
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;
#[derive(Clone)]
pub struct Primes<T: Num + ToPrimitive> {
pub vector: Vec<T>,
pub set: HashSet<T>,
pub struct Primes<T> {
vector: Vec<T>,
set: HashSet<T>,
}
impl<T> Primes<T>
@@ -38,6 +38,7 @@ where
set.insert(prime);
}
}
vector.reverse(); // so that self.pop removes the smallest prime
Primes { vector, set }
}
@@ -70,6 +71,23 @@ where
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)]
@@ -80,6 +98,23 @@ mod test {
fn test_example_prime() {
let primes = Primes::get_between(2, 99_999);
assert!(primes.set.contains(&56003));
assert!(primes.set.contains(&56993));
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));
}
}