Created
October 29, 2019 07:53
-
-
Save RedL0tus/83314727f5268e25c3f1706e4aa8efdf to your computer and use it in GitHub Desktop.
USAMTS - 3/2/31: Brute force
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env run-cargo-script | |
//! USAMTS - 3/2/31 | |
//! | |
//! ```cargo | |
//! [dependencies] | |
//! num = "~0.2" | |
//! ``` | |
const LIMIT: u128 = 100; | |
const NUM_THREADS: usize = 8; | |
extern crate num; | |
use num::abs; | |
use num::Integer; | |
use std::fmt; | |
use std::thread; | |
use std::collections::HashMap; | |
#[derive(Clone, Copy, Debug)] | |
struct Source { | |
a: u128, | |
b: u128, | |
c: u128, | |
d: u128, | |
m: u128, | |
} | |
impl Source { | |
fn new(a: u128, b: u128, c: u128, d:u128, m: u128) -> Self { | |
Self { | |
a, | |
b, | |
c, | |
d, | |
m, | |
} | |
} | |
} | |
impl fmt::Display for Source { | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
write!(f, "a: {}, b: {}, c: {}, d: {}, m: {}", self.a, self.b, self.c, self.d, self.m) | |
} | |
} | |
#[derive(Default, Debug)] | |
struct ResultSet { | |
start: u128, | |
stop: u128, | |
count: usize, | |
set: HashMap<i128, Vec<Source>>, | |
} | |
impl ResultSet { | |
fn new(start: u128, stop: u128, count: usize) -> Self { | |
Self { | |
start, | |
stop, | |
count, | |
..Default::default() | |
} | |
} | |
fn is_empty(&self) -> bool { | |
return self.set.is_empty(); | |
} | |
fn add_result(&mut self, result: i128, source: Source) { | |
let mut source_set: Vec<Source> = if let Some(temp) = self.set.get(&result) { | |
temp.clone() | |
} else { | |
println!("New result: {}", result); | |
Vec::new() | |
}; | |
source_set.push(source); | |
self.set.insert(result, source_set); | |
} | |
} | |
impl fmt::Display for ResultSet { | |
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
if self.is_empty() { | |
write!(f, "No result from thread {} ({} to {})\n", self.count, self.start, self.stop) | |
} else { | |
let output: String = self.set.iter().map(|(key, value)| { | |
let mut count: u128 = 0; | |
let sources: String = value.iter().map(|source| { | |
count += 1; | |
format!(" [ Count: {}, Source: ({}) ]\n", count, source) | |
}).collect(); | |
format!(" Result: {}, Sources ({} total):\n{}", key, value.len(), sources) | |
}).collect::<String>(); | |
write!(f, "Result from thread {} ({} to {}):\n{}", self.count, self.start, self.stop, output) | |
} | |
} | |
} | |
fn run(start: u128, stop: u128, count: usize) -> ResultSet { | |
let mut result_set = ResultSet::new(start, stop, count); | |
for m in start..stop { | |
for a in 1..m { | |
for b in 1..a { | |
for c in 1..b { | |
for d in 1..c { | |
if ((a * m + b) as i128).gcd(&((c * m + d) as i128)) == 2019 { | |
let result: i128 = abs((a * d - b * c) as i128); | |
let source = Source::new(a, b, c, d, m); | |
result_set.add_result(result, source); | |
} | |
} | |
} | |
} | |
} | |
} | |
result_set | |
} | |
fn main(){ | |
let limit_per_thread: u128 = LIMIT / ((NUM_THREADS - 1) as u128); | |
let handles: Vec<thread::JoinHandle<ResultSet>> = (1..NUM_THREADS).map(|count| { | |
println!("Initializing thread {}", count); | |
thread::spawn(move || { | |
run(limit_per_thread * ((count as u128)- 1), limit_per_thread * (count as u128), count) | |
}) | |
}).collect(); | |
let mut results: Vec<ResultSet> = handles.into_iter().map(|handle| { | |
handle.join().expect("WTF???") | |
}).collect(); | |
results.push(run(limit_per_thread * ((NUM_THREADS - 1) as u128), LIMIT, NUM_THREADS)); | |
println!("\n === Calculation finished === \n"); | |
for result in results { | |
println!("{}", result); | |
} | |
println!("All done!"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment