Exercism track submissions
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

UPDATED: parallel letter freq

+53 -63
+53 -63
rust/parallel-letter-frequency/src/lib.rs
··· 1 - use std::{collections::HashMap, sync::mpsc::channel, thread}; 1 + use std::{cmp::min, collections::HashMap, sync::mpsc::channel, thread, vec}; 2 2 3 - fn split_evenly<T>(n: usize, xs: &[T]) -> impl Iterator<Item = &[T]> { 4 - struct _Iter<'a, T>(usize, &'a [T]); 5 - 6 - impl<'a, T> Iterator for _Iter<'a, T> { 7 - type Item = &'a [T]; 8 - 9 - fn next(&mut self) -> Option<Self::Item> { 10 - if self.1.len() == 0 { 3 + fn process(s: &str) -> Vec<(char, usize)> { 4 + s.to_lowercase() 5 + .chars() 6 + .filter_map(|c| { 7 + if c.is_alphabetic() { 8 + Some((c, 1)) 9 + } else { 11 10 None 12 - } else if self.0 == 0 { 13 - Some(self.1) 14 - } else { 15 - let extra = if self.1.len() % self.0 == 0 { 0 } else { 1 }; 16 - let mid = self.1.len() / self.0 + extra; 17 - let (first, next) = self.1.split_at(mid); 18 - self.1 = next; 19 - self.0 -= 1; 20 - Some(first) 21 11 } 22 - } 23 - } 24 - 25 - _Iter(n, xs) 12 + }) 13 + .collect::<Vec<_>>() 26 14 } 27 15 28 - fn process_str(inp: Vec<String>) -> Vec<(char, usize)> { 29 - inp.iter() 30 - .flat_map(|xs| { 31 - xs.to_lowercase() 32 - .chars() 33 - .filter_map(|c| { 34 - if c.is_alphabetic() { 35 - Some((c, 1)) 36 - } else { 37 - None 38 - } 39 - }) 40 - .collect::<Vec<_>>() 41 - }) 42 - .collect() 43 - } 16 + pub fn frequency(input: &[&'static str], worker_count: usize) -> HashMap<char, usize> { 17 + let len = input.len(); 18 + let wc = min(len, worker_count); 44 19 45 - pub fn frequency(input: &[&str], worker_count: usize) -> HashMap<char, usize> { 46 20 if input.is_empty() { 47 21 HashMap::new() 48 22 } else { 49 - let vss: Vec<Vec<String>> = split_evenly(worker_count, input) 50 - .collect::<Vec<&[&str]>>() 51 - .iter() 52 - .map(|&a| a.iter().map(|&a| String::from(a)).collect()) 53 - .collect(); 23 + let (super_tx, super_rx) = channel(); 54 24 55 - let vss_c = vss.clone(); 56 - let (tx, rx) = channel(); 25 + let thread_pool = (0..wc) 26 + .map(|_| { 27 + let super_tx = super_tx.clone(); 28 + let (child_tx, child_rx) = channel(); 29 + thread::spawn(move || { 30 + let mut p_cs: Vec<(char, usize)> = vec![]; 31 + for s in child_rx { 32 + match s { 33 + Some(x) => { 34 + p_cs.append(&mut process(x)); 35 + } 36 + None => { 37 + super_tx.send(p_cs).unwrap(); 38 + break; 39 + } 40 + } 41 + } 42 + }); 43 + child_tx 44 + }) 45 + .collect::<Vec<_>>(); 57 46 58 - vss.into_iter().for_each(|s| { 59 - let tx = tx.clone(); 60 - thread::spawn(move || { 61 - let cs: Vec<(char, usize)> = process_str(s); 62 - tx.send(cs).unwrap(); 47 + input 48 + .iter() 49 + .zip(thread_pool.iter().cycle()) 50 + .for_each(|(&s, child_tx)| { 51 + child_tx.send(Some(s)).unwrap(); 63 52 }); 64 - }); 65 - 66 53 67 - let mut r: HashMap<char, usize> = HashMap::new(); 68 - for _ in vss_c { 69 - r = match rx.recv() { 70 - Ok(v) => v.iter().fold(r, |mut acc, (c, count)| { 71 - acc.entry(*c).and_modify(|x| *x += 1).or_insert(*count); 72 - acc 73 - }), 74 - _ => r, 54 + let mut r: HashMap<char, usize> = HashMap::new(); 55 + for child_tx in thread_pool.iter() { 56 + child_tx 57 + .send(None) 58 + .expect("stop sending any more values to child channel"); 59 + r = match super_rx.recv() { 60 + Ok(v) => v.iter().fold(r, |mut acc, (c, count)| { 61 + acc.entry(*c).and_modify(|x| *x += 1).or_insert(*count); 62 + acc 63 + }), 64 + _ => r, 65 + } 75 66 } 67 + r 76 68 } 77 - r 78 - } 79 69 }