2019-03-27 16:05:08 +01:00
extern crate ramp ;
use ramp ::Int ;
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-25 11:02:52 +01:00
use std ::thread ;
// use std::sync::mpsc;
use std ::sync ::{ Arc , Barrier , RwLock } ;
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 {
2019-03-28 02:13:26 +01:00
fn per_mul ( & self ) -> i32 ;
2019-03-27 16:05:08 +01:00
}
impl Peristance for Int {
2019-03-28 02:13:26 +01:00
fn per_mul ( & self ) -> i32 {
2019-03-27 16:05:08 +01:00
let mut n = self . to_str_radix ( 10 , false )
. chars ( )
2019-03-28 02:13:26 +01:00
. map ( | x | x as i32 - 48 )
. fold ( Int ::one ( ) , | acc , x | acc * x ) ;
2019-03-25 11:02:52 +01:00
let mut counter = 1 ;
2019-03-27 16:05:08 +01:00
while n . to_str_radix ( 10 , false ) . chars ( ) . count ( ) > 1 {
n = n . to_str_radix ( 10 , false )
. chars ( )
2019-03-28 02:13:26 +01:00
. map ( | x | x as i32 - 48 )
. fold ( Int ::one ( ) , | acc , x | acc * x ) ;
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-27 16:05:08 +01:00
count : Int ,
2019-03-28 02:13:26 +01:00
step : i32 ,
offset : i32
2019-03-24 18:07:14 +01:00
}
impl Counter {
2019-03-28 02:13:26 +01:00
fn new ( _step : i32 , _offset : i32 ) -> Counter {
2019-03-27 16:05:08 +01:00
Counter { count : Int ::zero ( ) , step : _step , offset : _offset }
2019-03-24 18:07:14 +01:00
}
}
impl Iterator for Counter {
2019-03-27 16:05:08 +01:00
type Item = Int ;
2019-03-24 18:07:14 +01:00
2019-03-27 16:05:08 +01:00
fn next ( & mut self ) -> Option < Int > {
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 ( ) ;
2019-03-28 02:13:26 +01:00
let mut cpus = value_t! ( args , " jobs " , i32 ) . unwrap_or ( num_cpus ::get ( ) as i32 ) ;
2019-03-26 12:38:50 +01:00
if cpus = = 0 {
2019-03-28 02:13:26 +01:00
cpus = num_cpus ::get ( ) as i32 ;
2019-03-26 12:38:50 +01:00
}
let cpus = cpus ;
2019-03-28 02:13:26 +01:00
let max : i32 = value_t! ( args , " max " , i32 ) . unwrap_or ( 11 i32 ) ;
2019-03-26 12:38:50 +01:00
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-28 02:13:26 +01:00
let mut top : i32 = 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
}