a-conjecture-of-mine

An exercise on polyglossy: the same problem solved on multiple languages

commit fbd0555b91f701ea72f6027d4d7d7a1c36540ffd
parent adfd52d53c6f4a6b1e0a0dd1cbf5b06f0afdf470
Author: Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>
Date:   Sat,  3 Nov 2018 16:29:00 -0300

Implemented multi-threading functionality.

Diffstat:
MCargo.lock | 49+++++++++++++++++++++++++++++++++++++------------
MCargo.toml | 5++---
Msrc/main.rs | 182+++++++++++++++++++++++++++++++------------------------------------------------
3 files changed, 110 insertions(+), 126 deletions(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -2,30 +2,55 @@
 name = "conjecture_tester"
 version = "0.1.0"
 dependencies = [
- "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "crossterm 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
-name = "kernel32-sys"
-version = "0.2.2"
+name = "crossterm"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
+ "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "libc"
+version = "0.2.43"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+
+[[package]]
+name = "termios"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "winapi"
-version = "0.2.8"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
-name = "winapi-build"
-version = "0.1.1"
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [metadata]
-"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
-"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
-"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
+"checksum crossterm 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3069b1b614f818b56d12eabb91d3fe39bfedb40d99f111b07969ac86039ce60e"
+"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d"
+"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625"
+"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
+"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
diff --git a/Cargo.toml b/Cargo.toml
@@ -4,5 +4,4 @@ version = "0.1.0"
 authors = ["Gark Garcia <37553739+GarkGarcia@users.noreply.github.com>"]
 
 [dependencies]
-winapi = "0.2.8"
-kernel32-sys = "0.2.1"-
\ No newline at end of file
+crossterm = "0.4.0"+
\ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
@@ -3,28 +3,28 @@
 // Let S: N -> N be the sum of the digits of a positive integer.
 // For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger.
 
-extern crate kernel32;
-extern crate winapi;
-
-use winapi::HANDLE;
-use winapi::wincon::CONSOLE_SCREEN_BUFFER_INFO;
-use winapi::wincon::COORD;
-use winapi::wincon::SMALL_RECT;
-use winapi::WORD;
-use winapi::DWORD;
-use std::io::stdin;
+extern crate crossterm;
 
-static mut CONSOLE_HANDLE: Option<HANDLE> = None;
+use std::io::stdin;
+use std::sync::mpsc::{Sender, Receiver};
+use std::sync::mpsc;
+use std::thread;
+use std::ops::Range;
+use crossterm::terminal::{terminal,ClearType};
+use crossterm::Screen;
 
 fn main() {
+    let screen = Screen::default();
+    let prompt = terminal(&screen);
+
     let mut user_input = String::new();
 
-    println!("  This program is a simple test for the following conjecture:
+    println!("This program is a simple test for the following conjecture:
     
-  Let S: N -> N be the sum of the digits of a positive integer.
-  For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger.
+Let S: N -> N be the sum of the digits of a positive integer.
+For all A and B in N, S(A + B) = S(A) + S(B) - 9k, where k is an interger.
     
-  What value would you like to test the conjecture for?");
+What value would you like to test the conjecture for?");
 
     // Listen for user input
     stdin().read_line(&mut user_input).expect("Did not enter a correct string");
@@ -32,18 +32,20 @@ fn main() {
 
     // If the user input is a valid int
     if !input_parsing_result.is_err() {
+        println!("\nLOADING...");
+
         let max = input_parsing_result.unwrap().abs();
-        let counter_examples = get_counter_expl(max);
+        let counterexpls = get_all_countrexpls(max);
 
         // Print the results
-        clear_console();
-        if counter_examples.len() == 0 {
+        prompt.clear(ClearType::CurrentLine);
+        if counterexpls.len() == 0 {
             println!("The conjecture is proved for all natural numbers smaller or equals to {}!", max);
         } else {
             println!("The conjecture is disproved! Here are the counter examples:");
 
-            for pair in counter_examples {
-                println!("{} and {};", pair[0], pair[1]);
+            for pair in counterexpls {
+                println!("{} and {}", pair[0], pair[1]);
             }
         }
     } else {
@@ -51,121 +53,79 @@ fn main() {
     }
 }
 
-// Test the conjecture for all values up to max and return the counterexamples
-fn get_counter_expl(max : i32) -> Vec<[i32; 2]> {
-    let mut counter_examples : Vec<[i32; 2]> = Vec::new();
-    let mut load_bar = 0;
+fn get_all_countrexpls(max: i32) -> Vec<[i32; 2]> {
+
+    if max > 1000 {
+        
+        // Thread related variables
+        let (coutexpl_sender, coutexpl_reciever): (Sender<Vec<[i32; 2]>>, Receiver<Vec<[i32; 2]>>) = mpsc::channel();
+        let mut child_threads = Vec::new();
+        let n_threads = 10;
+        let range_lenght = ((max as f32) / n_threads as f32).ceil() as i32;
+
+        // Conjecture related variables
+        let mut counterexpls: Vec<[i32; 2]> = Vec::new();
+
+        for i in 0..n_threads {
+            let thread_countr_sd = coutexpl_sender.clone();
+            let end = std::cmp::min(i * (range_lenght + 1) + range_lenght, max);
+            let range = Range {start: i * (range_lenght + 1), end: end};
+
+            let child = thread::spawn(move || {
+                thread_countr_sd.send(get_range_countrexpls(range, max))
+                    .expect("The thread was unable to sent a message trought the channel");
+            });
+            child_threads.push(child);
+        }
 
-    for a in 0..max {
+        for _ in 0..n_threads {
+            counterexpls.append(&mut coutexpl_reciever.recv().unwrap());
+        }
 
-        // Print the progress on the screen
-        let new_load_bar = a * 100 / max;
-        if new_load_bar != load_bar {
-            load_bar = new_load_bar;
-            clear_console();
-            println!("LOADING: {}%", new_load_bar);
+        for child in child_threads {
+            child.join().expect("Child thread panicked");
         }
 
+        return counterexpls;
+
+    } else {
+        return get_range_countrexpls(0..max, max);
+    }
+}
+
+fn get_range_countrexpls(range: Range<i32>, max: i32) -> Vec<[i32; 2]> {
+    let mut counterexpls = Vec::new();
+
+    for a in range {
         for b in a..max {
-            let difference : i32 = sum_digits(a + b) - sum_digits(a) - sum_digits(b);
+            let difference: i32 = sum_digits(a + b) - sum_digits(a) - sum_digits(b);
 
             if !is_multiple_of_nine(difference) {
-                counter_examples.push([a, b]);
+                counterexpls.push([a, b]);
             }
         }
     }
 
-    return counter_examples;
+    return counterexpls;
 }
 
-fn is_multiple_of_nine(n : i32) -> bool {
+fn is_multiple_of_nine(n: i32) -> bool {
     let n_float = n as f32;
 
     return (n_float/9f32) % 1f32 == 0f32;
 }
 
-fn get_digits(n : i32) -> Vec<u32> {
+fn get_digits(n: i32) -> Vec<u32> {
     return n.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect();
 }
 
-fn sum_digits(n : i32) -> i32 {
-    let mut sum : i32 = 0i32;
+fn sum_digits(n: i32) -> i32 {
+    let mut sum = 0;
 
     for d in get_digits(n) {
-        let d_ = d as i32;
-        sum += d_;
+        let _d = d as i32;
+        sum += _d;
     }
 
     return sum;
 }
-
-
-// Console releted code:
-
-fn get_output_handle() -> HANDLE {
-    unsafe {
-        if let Some(handle) = CONSOLE_HANDLE {
-            return handle;
-        } else {
-            let handle = kernel32::GetStdHandle(winapi::STD_OUTPUT_HANDLE);
-            CONSOLE_HANDLE = Some(handle);
-            return handle;
-        }
-    }
-}
-
-fn get_buffer_info() -> winapi::CONSOLE_SCREEN_BUFFER_INFO {
-    let handle = get_output_handle();
-    if handle == winapi::INVALID_HANDLE_VALUE {
-        panic!("NoConsole")
-    }
-    let mut buffer = CONSOLE_SCREEN_BUFFER_INFO {
-        dwSize: COORD { X: 0, Y: 0 },
-        dwCursorPosition: COORD { X: 0, Y: 0 },
-        wAttributes: 0 as WORD,
-        srWindow: SMALL_RECT {
-            Left: 0,
-            Top: 0,
-            Right: 0,
-            Bottom: 0,
-        },
-        dwMaximumWindowSize: COORD { X: 0, Y: 0 },
-    };
-    unsafe {
-        kernel32::GetConsoleScreenBufferInfo(handle, &mut buffer);
-    }
-    buffer
-}
-
-fn clear_console() {
-    let handle = get_output_handle();
-    if handle == winapi::INVALID_HANDLE_VALUE {
-        panic!("NoConsole")
-    }
-
-    let screen_buffer = get_buffer_info();
-    let console_size: DWORD = screen_buffer.dwSize.X as u32 * screen_buffer.dwSize.Y as u32;
-    let coord_screen = COORD { X: 0, Y: 0 };
-
-    let mut amount_chart_written: DWORD = 0;
-    unsafe {
-        kernel32::FillConsoleOutputCharacterW(
-            handle,
-            32 as winapi::WCHAR,
-            console_size,
-            coord_screen,
-            &mut amount_chart_written,
-        );
-    }
-    set_cursor_possition(0, 0);
-}
-
-fn set_cursor_possition(y: i16, x: i16) {
-    let handle = get_output_handle();
-    if handle == winapi::INVALID_HANDLE_VALUE {
-        panic!("NoConsole")
-    }
-    unsafe {
-        kernel32::SetConsoleCursorPosition(handle, COORD { X: x, Y: y });
-    }
-}