divide repository in src and lib
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "combination"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,105 @@
|
||||
pub struct PositionCombinations {
|
||||
min_length: usize,
|
||||
max_length: usize,
|
||||
state: Vec<bool>,
|
||||
finished: bool,
|
||||
}
|
||||
|
||||
impl Iterator for PositionCombinations {
|
||||
type Item = Vec<bool>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
let result = self.state.clone();
|
||||
self.increment();
|
||||
if self.finished {
|
||||
return None;
|
||||
}
|
||||
if (self.min_length..=self.max_length).contains(&result.iter().filter(|x| **x).count())
|
||||
{
|
||||
return Some(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PositionCombinations {
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
fn increment(&mut self) {
|
||||
let mut overflow = self.state[0];
|
||||
self.state[0] ^= true;
|
||||
for position in self.state[1..].iter_mut() {
|
||||
let new_overflow = *position & overflow;
|
||||
*position ^= overflow;
|
||||
overflow = new_overflow;
|
||||
}
|
||||
if overflow {
|
||||
self.finished = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
use crate::combination::PositionCombinations;
|
||||
use std::collections::HashSet;
|
||||
|
||||
#[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]);
|
||||
solution.insert(vec![false, true, false, true]);
|
||||
solution.insert(vec![false, true, true, false]);
|
||||
solution.insert(vec![false, true, true, true]);
|
||||
solution.insert(vec![true, true, false, false]);
|
||||
solution.insert(vec![true, false, true, false]);
|
||||
solution.insert(vec![true, false, false, true]);
|
||||
solution.insert(vec![true, false, true, true]);
|
||||
solution.insert(vec![true, true, false, true]);
|
||||
solution.insert(vec![true, true, true, false]);
|
||||
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;
|
||||
}
|
||||
assert_eq!(number_solutions, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "macros"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,5 @@
|
||||
#[allow(unused_macros)]
|
||||
|
||||
macro_rules! dbg_println {
|
||||
($($arg:tt)*) => (#[cfg(debug_assertions)] println!($($arg)*));
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "primes"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num = "*"
|
||||
@@ -0,0 +1,120 @@
|
||||
extern crate num;
|
||||
|
||||
use num::FromPrimitive;
|
||||
use num::Num;
|
||||
use num::ToPrimitive;
|
||||
use std::collections::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Primes<T> {
|
||||
vector: Vec<T>,
|
||||
set: HashSet<T>,
|
||||
}
|
||||
|
||||
impl<T> Primes<T>
|
||||
where
|
||||
T: Num + ToPrimitive + FromPrimitive + Hash + Eq + PartialEq + Copy,
|
||||
{
|
||||
pub fn get_between(min_value: T, max_value: T) -> Self {
|
||||
let max_value = max_value.to_usize().unwrap();
|
||||
let min_value = min_value.to_usize().unwrap();
|
||||
assert!(min_value > 1);
|
||||
assert!(max_value > min_value);
|
||||
Self::from_array(
|
||||
Self::get_prime_numbers_array(&min_value, &max_value),
|
||||
&min_value,
|
||||
&max_value,
|
||||
)
|
||||
}
|
||||
|
||||
fn from_array(array: Vec<bool>, min_value: &usize, max_value: &usize) -> Self {
|
||||
let mut vector = Vec::new();
|
||||
let mut set = HashSet::new();
|
||||
for number in *min_value..*max_value {
|
||||
if array[(number - min_value) as usize] {
|
||||
let prime = FromPrimitive::from_usize(number).unwrap();
|
||||
vector.push(prime);
|
||||
set.insert(prime);
|
||||
}
|
||||
}
|
||||
vector.reverse(); // so that self.pop removes the smallest prime
|
||||
Primes { vector, set }
|
||||
}
|
||||
|
||||
fn get_prime_numbers_array(min_value: &usize, max_value: &usize) -> Vec<bool> {
|
||||
// Sieve of Eratosthenes
|
||||
let length = *max_value - *min_value;
|
||||
let mut result = vec![true; length];
|
||||
|
||||
for number_to_check in 2..(max_value / 2) {
|
||||
let mut last_number = number_to_check;
|
||||
loop {
|
||||
let current_number = last_number + number_to_check;
|
||||
if current_number < *min_value {
|
||||
last_number = current_number;
|
||||
continue;
|
||||
}
|
||||
if current_number >= *max_value {
|
||||
break;
|
||||
}
|
||||
result[current_number - min_value] = false;
|
||||
last_number = current_number;
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn remove(&mut self, num: &T) {
|
||||
if let Some(index) = self.vector.iter().position(|x| x == num) {
|
||||
self.vector.remove(index);
|
||||
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)]
|
||||
mod test {
|
||||
use crate::primes::Primes;
|
||||
|
||||
#[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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user