From bb77b2d5457977168467d836929a1362a9c0c50d Mon Sep 17 00:00:00 2001 From: Michael Preisach Date: Mon, 28 May 2018 00:27:14 +0200 Subject: [PATCH] level 4 works on multithreading --- Cargo.lock | 10 +++ Cargo.toml | 1 + day4.txt | 1 + src/day4.rs | 184 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 16 +++++ src/tests.rs | 24 +++++++ 6 files changed, 236 insertions(+) create mode 100644 day4.txt create mode 100644 src/day4.rs diff --git a/Cargo.lock b/Cargo.lock index 220146c..659355f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,4 +1,14 @@ [[package]] name = "adventofcode2015" version = "0.1.0" +dependencies = [ + "md5 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] +[[package]] +name = "md5" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum md5 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "daa1004633f76cdcd5a9d83ffcfe615e30ca7a2a638fcc8b8039a2dac21289d7" diff --git a/Cargo.toml b/Cargo.toml index ba6d3d3..27c6eb1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,4 @@ version = "0.1.0" authors = ["Michael Preisach "] [dependencies] +md5 = "0.3.7" \ No newline at end of file diff --git a/day4.txt b/day4.txt new file mode 100644 index 0000000..922d9e6 --- /dev/null +++ b/day4.txt @@ -0,0 +1 @@ +bgvyzdsv \ No newline at end of file diff --git a/src/day4.rs b/src/day4.rs new file mode 100644 index 0000000..2c827f5 --- /dev/null +++ b/src/day4.rs @@ -0,0 +1,184 @@ +extern crate md5; + +use std; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::sync::mpsc::channel; + +pub struct Data { + base: String, +} + + +struct SharedData { + dig: md5::Digest, + i: u64, + valid: bool, +} + +struct Slice { + next: u64, + size: u64, + run: bool, +} + +impl Data { + pub fn new() -> Data { + Data { + base: String::new(), + } + } + + pub fn parse(&mut self, input: String) { + self.base = input; + } + + + pub fn mine5(&mut self) -> u64 { + for i in 0..std::u64::MAX { + let key = format!("{}{}",self.base, i.to_string()); + let res = md5::compute(key.as_bytes()); + if res[0] == 0 && res[1] == 0 && (res[2] & 0xF0) == 0 { + println!("{}: {} -> {:x}", i, key, res); + return i; + } + } + 0 + } + + pub fn mine5_mt(&mut self) -> u64 { + let threads = 16; + let (tx, rx) = channel(); + let mut slice = Slice{next: 0, size: 100, run: true}; + let slice_mut = Arc::new(Mutex::new(slice)); + let mut result : u64 = 0; + + for i in 0 .. threads { + let local_base = self.base.clone(); + let local_tx = tx.clone(); + let local_slice = slice_mut.clone(); + thread::spawn(move || { + let mut count : u64; + let mut target : u64; + let mut run = true; + let mut result = SharedData { + i: 0, + dig: md5::compute(b"0"), + valid: false, + }; + while run { + { + let mut local_slice_mut = local_slice.lock().unwrap(); + run = local_slice_mut.run; + count = local_slice_mut.next; + if count <= (std::u64::MAX - local_slice_mut.size) { + target = count + local_slice_mut.size; + } else { + target = std::u64::MAX; + } + local_slice_mut.next = target; + } + + while run && count < target { + let key = format!("{}{}", local_base, count.to_string()); + result.dig = md5::compute(key.as_bytes()); + if result.dig[0] == 0 && result.dig[1] == 0 && (result.dig[2] & 0xF0) == 0 { + println!("{}: {} -> {:x}", count, key, result.dig); + result.i = count; + result.valid = true; + run = false; + let mut local_slice_mut = local_slice.lock().unwrap(); + local_slice_mut.run = false; + } else { + count += 1; + } + } + } + local_tx.send(result); + + }); + } + + for _ in 0 .. threads { + let res = rx.recv(); + match res { + Ok(val) => { + if val.valid && (result == 0 || result > val.i) { + result = val.i; + } + }, + Err(_) => (), + } + } + result + + } + + pub fn mine6_mt(&mut self) -> u64 { + let threads = 16; + let (tx, rx) = channel(); + let mut slice = Slice{next: 0, size: 100, run: true}; + let slice_mut = Arc::new(Mutex::new(slice)); + let mut result : u64 = 0; + + for i in 0 .. threads { + let local_base = self.base.clone(); + let local_tx = tx.clone(); + let local_slice = slice_mut.clone(); + thread::spawn(move || { + let mut count : u64; + let mut target : u64; + let mut run = true; + let mut result = SharedData { + i: 0, + dig: md5::compute(b"0"), + valid: false, + }; + while run { + { + let mut local_slice_mut = local_slice.lock().unwrap(); + run = local_slice_mut.run; + count = local_slice_mut.next; + if count <= (std::u64::MAX - local_slice_mut.size) { + target = count + local_slice_mut.size; + } else { + target = std::u64::MAX; + } + local_slice_mut.next = target; + } + + while run && count < target { + let key = format!("{}{}", local_base, count.to_string()); + result.dig = md5::compute(key.as_bytes()); + if result.dig[0] == 0 && result.dig[1] == 0 && result.dig[2] == 0 { + println!("{}: {} -> {:x}", count, key, result.dig); + result.i = count; + result.valid = true; + run = false; + let mut local_slice_mut = local_slice.lock().unwrap(); + local_slice_mut.run = false; + } else { + count += 1; + } + } + } + local_tx.send(result); + + }); + } + + for _ in 0 .. threads { + let res = rx.recv(); + match res { + Ok(val) => { + if val.valid && (result == 0 || result > val.i) { + result = val.i; + } + }, + Err(_) => (), + } + } + result + + } +} diff --git a/src/main.rs b/src/main.rs index 167d78b..dd97bc4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod day1; mod day2; mod day3; +mod day4; mod tests; @@ -52,4 +53,19 @@ fn main() { } Err(msg) => println!("{}",msg), }; + + match File::open("day4.txt") { + Ok(mut f) => { + let mut input = String::new(); + match f.read_to_string(&mut input) { + Ok(_) => (), + Err(msg) => println!("{}",msg), + } + let mut d4 = day4::Data::new(); + d4.parse(input); + println!("day4 mine: {}", d4.mine5_mt()); + println!("day3 robot: {}", d4.mine6_mt()); + } + Err(msg) => println!("{}",msg), + }; } diff --git a/src/tests.rs b/src/tests.rs index 6285ccc..dd7f2e9 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -164,3 +164,27 @@ fn day3_4() { res = day3.robot(); assert_eq!(res, 11); } + +#[test] +fn day4_1() { + let input = String::from("abcdef"); + let mut day4 = day4::Data::new(); + day4.parse(input); + let mut res = day4.mine_mt(); + assert_eq!(res, 609043); + +// res = day4.robot(); +// assert_eq!(res, 11); +} + +#[test] +fn day4_2() { + let input = String::from("pqrstuv"); + let mut day4 = day4::Data::new(); + day4.parse(input); + let mut res = day4.mine_mt(); + assert_eq!(res, 1048970); + +// res = day4.robot(); +// assert_eq!(res, 11); +}