Advertisement
Guest User

Advent of Code Day 5 Part 1/2 parallel (thread exit fixed)

a guest
Dec 6th, 2016
122
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Rust 4.18 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.    
  49.     const PASSWORD_LEN: usize = 8;
  50.  
  51.     // create threads
  52.     for i in 0..thcnt {
  53.         let thtx = thtx.clone();
  54.         let (maintx, thrx) = channel();
  55.         maintxs.push(maintx);
  56.  
  57.         thread::spawn(move||{
  58.             let mut idx = i;
  59.             let mut buf = String::with_capacity(10);
  60.             let mut syncpoint = 1_000_000;
  61.             let syncstep = 1_000_000;
  62.             let mut res = [0u8; 16];
  63.             loop {
  64.                 let mut sh1 = sh.clone();
  65.                 write!(&mut buf, "{}", idx).unwrap();
  66.                 sh1.input_str(&buf);
  67.                 buf.clear();
  68.                 sh1.result(&mut res);
  69.                 if res[0] == 0 && res[1] == 0 && res[2]>>4 == 0 {
  70.                     thtx.send(Part1Digit(to_hex(res[2] & 0xf), idx)).unwrap();
  71.                     let i = (res[2]&0xf) as usize;
  72.                     thtx.send(Digit(i, to_hex(res[3] >> 4), idx)).unwrap();
  73.                 };
  74.                 idx += thcnt;
  75.                 if idx >= syncpoint {
  76.                     thtx.send(GroupSync).unwrap();
  77.                     // wait other threads
  78.                     match thrx.recv().unwrap() {
  79.                         Ack => (),
  80.                         Die => return,
  81.                     }
  82.                     syncpoint += syncstep;
  83.                 }
  84.             }
  85.         });
  86.     }
  87.  
  88.     // collect thread data
  89.     let mut code1 = vec![];
  90.     let mut code2 = vec![(0xffff_ffff_ffff_ffffu64, '_'); PASSWORD_LEN];
  91.     let mut synccnt = 0;
  92.     loop {
  93.         match mainrx.recv().unwrap() {
  94.             GroupSync => {
  95.                 synccnt += 1;
  96.                 if synccnt == thcnt {
  97.                     // all threads reached GroupSync state
  98.                     // check for completion
  99.                     if code2.iter().all(|&(_, ch)| ch != '_') && code1.len() == PASSWORD_LEN {
  100.                         print!("Password1: ");
  101.                         for &(_, ch) in &code1 {
  102.                             print!("{}", ch);
  103.                         }
  104.                         println!("");
  105.                         print!("Password2: ");
  106.                         for &(_, ch) in &code2 {
  107.                             print!("{}", ch);
  108.                         }
  109.                         println!("");
  110.                         // done
  111.                         for tx in &maintxs {
  112.                             tx.send(Die).unwrap();
  113.                         };
  114.                         break;
  115.                     }
  116.                    
  117.                     synccnt = 0;
  118.                     // allow threads to continue
  119.                     for tx in &maintxs {
  120.                         tx.send(Ack).unwrap();
  121.                     };
  122.                 };
  123.             },
  124.             Digit(i, ch, idx) => {
  125.                 if i < PASSWORD_LEN && code2[i].0 > idx {
  126.                     code2[i] = (idx, ch);
  127.                 }
  128.                 print!("Decoding: ");
  129.                 for &(_, c) in &code2 {
  130.                     print!("{}", if c == '_' {ch} else {c});
  131.                 }
  132.                 print!("\r");
  133.                 io::Write::flush(&mut io::stdout()).unwrap();
  134.             },
  135.             Part1Digit(ch, idx) => {
  136.                 code1.push((idx, ch));
  137.                 code1.sort();
  138.                 code1.truncate(PASSWORD_LEN);
  139.             }
  140.         }
  141.     }
  142. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement