73 lines
1.8 KiB
Rust
73 lines
1.8 KiB
Rust
use std::{
|
|
sync::{mpsc, Arc, Mutex},
|
|
thread,
|
|
};
|
|
|
|
pub fn process_part1(input: &str) -> i64 {
|
|
let mut n = 1;
|
|
loop {
|
|
let hash = md5::compute(format!("{input}{n}"));
|
|
let hash = format!("{hash:x}");
|
|
if hash.split_at(5).0 == "00000" {
|
|
break;
|
|
}
|
|
n += 1;
|
|
}
|
|
n
|
|
}
|
|
|
|
pub fn process_part2(input: &str) -> i64 {
|
|
let threads = thread::available_parallelism().unwrap().get();
|
|
|
|
let found = Arc::new(Mutex::new(false));
|
|
|
|
let (tx, rx) = mpsc::channel();
|
|
thread::scope(|s| {
|
|
for thread in 0..threads {
|
|
let tx_clone = tx.clone();
|
|
let found_clone = found.clone();
|
|
s.spawn(move || {
|
|
let mut n = thread + 1;
|
|
loop {
|
|
{
|
|
if *found_clone.lock().unwrap() {
|
|
break;
|
|
}
|
|
}
|
|
let hash = md5::compute(format!("{input}{n}"));
|
|
let hash = format!("{hash:x}");
|
|
if hash.split_at(6).0 == "000000" {
|
|
let _ = tx_clone.send(n);
|
|
let mut found_guard = found_clone.lock().unwrap();
|
|
*found_guard = true;
|
|
break;
|
|
}
|
|
n += 1;
|
|
}
|
|
});
|
|
}
|
|
drop(tx);
|
|
let mut res = vec![];
|
|
while let Ok(n) = rx.recv() {
|
|
res.push(n);
|
|
}
|
|
*res.iter().min().unwrap() as i64
|
|
})
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
const INPUT1: &str = "abcdef";
|
|
const INPUT2: &str = "pqrstuv";
|
|
|
|
#[test]
|
|
fn part1() {
|
|
let result = process_part1(INPUT1);
|
|
assert_eq!(result, 609043);
|
|
let result = process_part1(INPUT2);
|
|
assert_eq!(result, 1048970);
|
|
}
|
|
}
|