Browse Source

level 4 works on multithreading

master
Michael Preisach 8 years ago
parent
commit
bb77b2d545
  1. 10
      Cargo.lock
  2. 1
      Cargo.toml
  3. 1
      day4.txt
  4. 184
      src/day4.rs
  5. 16
      src/main.rs
  6. 24
      src/tests.rs

10
Cargo.lock

@ -1,4 +1,14 @@
[[package]] [[package]]
name = "adventofcode2015" name = "adventofcode2015"
version = "0.1.0" 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"

1
Cargo.toml

@ -4,3 +4,4 @@ version = "0.1.0"
authors = ["Michael Preisach <michael@preisach.at>"] authors = ["Michael Preisach <michael@preisach.at>"]
[dependencies] [dependencies]
md5 = "0.3.7"

1
day4.txt

@ -0,0 +1 @@
bgvyzdsv

184
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
}
}

16
src/main.rs

@ -1,6 +1,7 @@
mod day1; mod day1;
mod day2; mod day2;
mod day3; mod day3;
mod day4;
mod tests; mod tests;
@ -52,4 +53,19 @@ fn main() {
} }
Err(msg) => println!("{}",msg), 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),
};
} }

24
src/tests.rs

@ -164,3 +164,27 @@ fn day3_4() {
res = day3.robot(); res = day3.robot();
assert_eq!(res, 11); 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);
}

Loading…
Cancel
Save