Advertisement
Guest User

Advent of Code Day 5 Part 1/2 parallel + yield_now()

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