2019-03-22 15:47:19 +01:00
extern crate num_bigint ;
// extern crate num_traits;
2019-03-25 11:02:52 +01:00
extern crate num_cpus ;
2019-03-26 12:38:50 +01:00
#[ macro_use ]
extern crate clap ;
2019-03-25 11:02:52 +01:00
2019-03-22 15:47:19 +01:00
2019-03-26 12:38:50 +01:00
use clap ::App ;
2019-03-22 15:47:19 +01:00
use num_bigint ::BigUint ;
2019-03-25 11:02:52 +01:00
use std ::thread ;
// use std::sync::mpsc;
use std ::sync ::{ Arc , Barrier , RwLock } ;
2019-03-26 12:38:50 +01:00
2019-03-25 23:20:15 +01:00
use std ::time ::{ Duration , Instant } ;
2019-03-25 11:02:52 +01:00
2019-03-26 12:38:50 +01:00
trait Peristance {
fn per_mul ( & self ) -> u8 ;
2019-03-25 11:02:52 +01:00
}
2019-03-26 12:38:50 +01:00
impl Peristance for BigUint {
fn per_mul ( & self ) -> u8 {
let mut n = self . to_radix_le ( 10 )
. into_iter ( )
. product ::< BigUint > ( ) ;
2019-03-25 11:02:52 +01:00
let mut counter = 1 ;
while n . to_str_radix ( 10 ) . chars ( ) . count ( ) > 1 {
2019-03-26 12:38:50 +01:00
n = n . to_radix_le ( 10 )
. into_iter ( )
. product ::< BigUint > ( ) ;
2019-03-25 11:02:52 +01:00
counter + = 1 ;
}
return counter ;
}
}
#[ derive(Debug) ]
2019-03-24 18:07:14 +01:00
struct Counter {
2019-03-25 11:02:52 +01:00
count : BigUint ,
step : u8 ,
offset : u8
2019-03-24 18:07:14 +01:00
}
impl Counter {
2019-03-25 11:02:52 +01:00
fn new ( _step : u8 , _offset : u8 ) -> Counter {
Counter { count : BigUint ::from ( 0 u8 ) , step : _step , offset : _offset }
2019-03-24 18:07:14 +01:00
}
}
impl Iterator for Counter {
type Item = BigUint ;
fn next ( & mut self ) -> Option < BigUint > {
2019-03-25 11:02:52 +01:00
// Increment our count. This is why we started at zero.
self . count + = self . step ;
Some ( self . count . clone ( ) )
2019-03-24 18:07:14 +01:00
}
}
fn main ( ) {
2019-03-25 23:20:15 +01:00
let start = Instant ::now ( ) ;
2019-03-22 15:47:19 +01:00
2019-03-26 12:38:50 +01:00
let args = App ::new ( " Persistance " )
. version ( " 0.2.0 " )
. author ( " Daniel Olsen " )
. about ( " Finds the sequence of smallest number with a multiplicative persistance of n " )
. args_from_usage ( " -j, --jobs=[threads] 'Sets the number of worker threads to spin up, if 0 or empty this equals the number of cores on your system (INCLUDING HYPERTHREADS)'
- m , - - max = [ max ] ' Sets the maximum n you want to calculate ' " )
. get_matches ( ) ;
let mut cpus = value_t! ( args , " jobs " , u8 ) . unwrap_or ( num_cpus ::get ( ) as u8 ) ;
if cpus = = 0 {
cpus = num_cpus ::get ( ) as u8 ;
}
let cpus = cpus ;
let max = value_t! ( args , " max " , u8 ) . unwrap_or ( 11 u8 ) ;
println! ( " threads: {} " , cpus ) ;
let barrier = Arc ::new ( Barrier ::new ( 2 ) ) ;
2019-03-25 11:02:52 +01:00
for thread in 0 .. ( cpus ) {
let c = barrier . clone ( ) ;
thread ::spawn ( move | | {
println! ( " Started thread {} ! " , thread ) ;
let counter = Counter ::new ( cpus - thread , cpus ) ;
2019-03-26 12:38:50 +01:00
let mut top : u8 = 0 ;
2019-03-25 11:02:52 +01:00
for x in counter {
2019-03-26 12:38:50 +01:00
let n = x . per_mul ( ) ;
if n > top {
top = n ;
println! ( " {:?} {} - {} : {} " , start . elapsed ( ) , thread , n , x ) ;
if n > max - 1 {
2019-03-25 11:02:52 +01:00
c . wait ( ) ;
return ;
}
}
}
} ) ;
}
barrier . wait ( ) ;
2019-03-26 12:38:50 +01:00
println! ( " Finding took {:#?} " , start . elapsed ( ) ) ;
2019-03-25 11:02:52 +01:00
return ;
2019-03-24 18:07:14 +01:00
}