Advertisement
Guest User

Advent of Code Day 5 parallel

a guest
Dec 6th, 2016
165
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 3.35 KB | None | 0 0
  1. extern crate crypto;
  2. extern crate num_cpus;
  3.  
  4. use crypto::md5::Md5;
  5. use crypto::digest::Digest;
  6. use std::fmt::Write;
  7. use std::io;
  8. use std::thread;
  9. use std::sync::mpsc::channel;
  10. use std::u64;
  11.  
  12. #[derive(Clone, Copy, Debug)]
  13. enum ThMsg {
  14.     Digit(usize, char, u64),
  15.     GroupSync,
  16. }
  17.  
  18. use ThMsg::{Digit, GroupSync};
  19.  
  20. #[derive(Clone, Copy, Debug)]
  21. enum MainMsg {
  22.     Ack,
  23. }
  24.  
  25. use MainMsg::Ack;
  26.  
  27. #[inline]
  28. fn to_hex(n: u8) -> char {
  29.     match n {
  30.         0...9 => (('0' as u8) + n) as char,
  31.         10...15 => (('a' as u8) + n - 10) as char,
  32.         _ => '#',
  33.     }
  34. }
  35.  
  36. fn main() {
  37.     let mut sh = Md5::new();
  38.     sh.input_str("ojvtpuvg");
  39.  
  40.     let thcnt = num_cpus::get() as u64;
  41.     println!("Starting {} threads", thcnt);
  42.  
  43.     let (thtx, mainrx) = channel();
  44.  
  45.     let mut maintxs = vec![];
  46.    
  47.     // create threads
  48.     for i in 0..thcnt {
  49.         let thtx = thtx.clone();
  50.         let (maintx, thrx) = channel();
  51.         maintxs.push(maintx);
  52.  
  53.         thread::spawn(move||{
  54.             let mut idx = i;
  55.             let mut buf = String::with_capacity(10);
  56.             let mut syncpoint = 1_000_000;
  57.             let syncstep = 1_000_000;
  58.             let mut res = [0u8; 16];
  59.             loop {
  60.                 let mut sh1 = sh.clone();
  61.                 write!(&mut buf, "{}", idx).unwrap();
  62.                 sh1.input_str(&buf);
  63.                 buf.clear();
  64.                 sh1.result(&mut res);
  65.                 if res[0] == 0 && res[1] == 0 && res[2]>>4 == 0 {
  66.                     let i = (res[2] & 0xf) as usize;
  67.                     if i < 8 {
  68.                         thtx.send(Digit(i, to_hex(res[3]>>4), idx)).unwrap();
  69.                     }
  70.                 }
  71.                 idx += thcnt;
  72.                 if idx >= syncpoint {
  73.                     thtx.send(GroupSync).unwrap();
  74.                     // wait other threads
  75.                     thrx.recv().unwrap();
  76.                     syncpoint += syncstep;
  77.                 }
  78.             }
  79.         });
  80.     }
  81.  
  82.     // collect thread data
  83.     let mut code2 = vec![(0xffff_ffff_ffff_ffffu64 ,'_'); 8];
  84.     let mut synccnt = 0;
  85.     loop {
  86.         match mainrx.recv().unwrap() {
  87.             GroupSync => {
  88.                 synccnt += 1;
  89.                 if synccnt == thcnt {
  90.                     // all threads reached GroupSync state
  91.                     // check for completion
  92.                     if code2.iter().all(|&(_, ch)| ch != '_') {
  93.                         println!("");
  94.                         for &(_, ch) in &code2 {
  95.                             print!("{}", ch);
  96.                         }
  97.                         println!("");
  98.                         // done
  99.                         break;
  100.                     }
  101.                     synccnt = 0;
  102.                     // allow threads to continue
  103.                     for tx in &maintxs {
  104.                         tx.send(Ack).unwrap();
  105.                     };
  106.                 };
  107.             },
  108.             Digit(i, ch, idx) => {
  109.                 if code2[i].0 > idx {
  110.                     code2[i] = (idx, ch);
  111.                 }
  112.                 print!("Decoding: ");
  113.                 for &(_, c) in &code2 {
  114.                     print!("{}", if c == '_' {ch} else {c});
  115.                 }
  116.                 print!("\r");
  117.                 io::Write::flush(&mut io::stdout()).unwrap();
  118.             },
  119.         }
  120.     }
  121. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement