diff --git a/Rust/src/main.rs b/Rust/src/main.rs
@@ -5,7 +5,13 @@
extern crate num_cpus;
-use std::{env, process, thread, sync::{Arc, mpsc::{self, Sender, Receiver}}};
+use std::{
+ env,
+ process,
+ thread,
+ sync::{Arc, Mutex, mpsc::{self, Sender, Receiver}},
+ collections::hash_map::{HashMap, Entry}
+};
const SUCCESS: i32 = 0;
const FAIL: i32 = 1;
@@ -28,7 +34,7 @@ fn main() {
};
match max_str.trim().parse::<usize>() {
- Ok(max) => if get_countrexpl(max, n_threads) {
+ Ok(max) => if countrexpl(max, n_threads) {
process::exit(FAIL);
} else {
process::exit(SUCCESS);
@@ -41,8 +47,8 @@ fn main() {
}
/// Distributes calculations across threads and collect the results
-fn get_countrexpl(max: usize, n_threads: usize) -> bool {
- let sums_cache = Arc::new(get_sums(max));
+fn countrexpl(max: usize, n_threads: usize) -> bool {
+ let sums_cache = Arc::new(Mutex::new(HashMap::with_capacity(max)));
if n_threads > 1 {
let (coutexpl_sender, coutexpl_reciever): (Sender<bool>, Receiver<bool>) = mpsc::channel();
@@ -56,7 +62,7 @@ fn get_countrexpl(max: usize, n_threads: usize) -> bool {
// value will get tested on a single thread and that all threads will perform roughtly the same number of operations
let thread_range = (i..max).step_by(n_threads);
- let child = thread::spawn(move || thread_countr_sd.send(get_iter_countrexpl(thread_range, thread_sums, max))
+ let child = thread::spawn(move || thread_countr_sd.send(iter_countrexpl(thread_range, thread_sums, max))
.expect(&format!("Thread n°{} was unable to sent a message trought the channel", i)));
child_threads.push(child);
@@ -71,19 +77,22 @@ fn get_countrexpl(max: usize, n_threads: usize) -> bool {
false
} else {
- get_iter_countrexpl(0..max, sums_cache, max)
+ iter_countrexpl(0..max, sums_cache, max)
}
}
/// Search for counterexamples among the items of a specif iterator.
-fn get_iter_countrexpl<I: IntoIterator<Item = usize>>(
+fn iter_countrexpl<I: IntoIterator<Item = usize>>(
iter: I,
- sums_cache: Arc<Vec<isize>>,
+ sums_cache: Arc<Mutex<HashMap<usize, isize>>>,
max: usize
) -> bool {
for a in iter {
for b in a..max {
- let diff = sums_cache[a + b] - sums_cache[a] - sums_cache[b];
+ let sum_a_b = lookup_or_insert(&sums_cache, a + b);
+ let sum_a = lookup_or_insert(&sums_cache, a);
+ let sum_b = lookup_or_insert(&sums_cache, b);
+ let diff = sum_a_b - sum_a - sum_b;
if diff % 9 != 0 {
return true;
@@ -106,13 +115,14 @@ fn sum_digits(n: usize) -> isize {
sum as isize
}
-fn get_sums(max: usize) -> Vec<isize> {
- let range_max = 2 * (max + 1);
- let mut output = Vec::with_capacity(range_max);
-
- for i in 0..range_max {
- output.push(sum_digits(i));
+fn lookup_or_insert(sums_cache: &Arc<Mutex<HashMap<usize, isize>>>, n: usize) -> isize {
+ if let Ok(ref mut sums_cache) = sums_cache.lock() {
+ match (*sums_cache).entry(n) {
+ Entry::Vacant(entry) => *(entry.insert(sum_digits(n))),
+ Entry::Occupied(entry) => *(entry.get())
+ }
+ } else {
+ unimplemented!()
}
-
- output
}
+