diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..eda1c01 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,62 @@ +extern crate clap; +extern crate rand; + +use clap::{Arg, App}; +use std::collections::vec_deque::VecDeque; +use std::io::{self, BufRead}; +use std::result::Result; + +fn some<R: rand::Rng, T: Iterator<Item = Result<String, io::Error>>>( + r: &mut R, + n: usize, + lines: T, +) -> Result<VecDeque<String>, io::Error> { + let mut result: VecDeque<String> = VecDeque::with_capacity(n); + fn push(v: &mut VecDeque<String>, n: usize, x: String) { + v.push_back(x); + if v.len() > n { + v.pop_front(); + } + }; + + for (i, line) in lines.enumerate() { + let line = line?; + if result.len() < n { + push(&mut result, n, line); + } else if r.gen_range(0, i) < n { + let victim = r.gen_range(0, n); + result.remove(victim); + push(&mut result, n, line); + } + } + return Ok(result); +} + +fn main() { + let matches = App::new("some") + .version("0.1") + .author("Kjetil Ørbekk <kj@orbekk.com>") + .arg( + Arg::with_name("lines") + .short("n") + .value_name("NUM") + .help("Number of lines to print") + .takes_value(true), + ) + .get_matches(); + let num_lines = matches + .value_of("lines") + .unwrap_or("10") + .parse::<usize>() + .expect("number of lines to print"); + let stdin = io::stdin(); + let lines = some(&mut rand::thread_rng(), num_lines, stdin.lock().lines()); + match lines { + Ok(lines) => { + for line in lines { + println!("{}", line); + } + } + Err(e) => println!("Error: {}", e), + } +} |