I'm attempting to use rust to tackle so Competitive Programming problems, but I'm having issues parsing input from stdin such as this:
2
abx
asdf
asdfq
we
adx
fsdaf
ffsd
Where the first line indicates the number of test cases and each test case is separated by a blank line.
My initial approach is to read all of stdin into a Std::io::BufReader like: let buffer = BufReader::new(io::stdin())
I understand how to I can loop through each line of the buffer using something like:
let buffer = BufReader::new(reader);
for line in buffer.lines() {
println!("{}", line?)
}
However, like in C++, I'm looking for some way where I can manually advance the buffer.lines() iterator, so that when I being my for loop, I'll be starting at the first word input, "abx". I anticipated that this would've given me the desired behavior:
let buffer = BufReader::new(io::stdin());
let mut input_iter = buffer.lines();
input_iter.next();
input_iter.next();
for line in input_iter {
println!("{:?}", line);
}
But the for loop in this case prints every line. I'm also curious if there are better means to ultimately achieve my goal as well. Thank you!
Whenever you use a for loop like that, it's going to read every remaining line. Since you can only use the standard library during competitive programming, I like to set up something like this:
use std::io::{stdin, BufReader, BufRead};
use std::error::Error;
struct Input<B> {
inner: B,
buffer: String,
}
impl<B: BufRead> Input<B> {
pub fn new(inner: B) -> Self {
Self {
inner,
buffer: String::new(),
}
}
pub fn line(&mut self) -> Line {
self.buffer.clear();
self.inner.read_line(&mut self.buffer).unwrap();
Line {
split: self.buffer.split_whitespace()
}
}
}
struct Line<'a> {
split: std::str::SplitWhitespace<'a>
}
impl<'a> Line<'a> {
fn next(&mut self) -> u32 {
self.split.next().unwrap().parse().unwrap()
}
fn pair(&mut self) -> (u32, u32) {
let a = self.next();
let b = self.next();
(a, b)
}
}
fn main() -> Result<(), Box<dyn Error>> {
let input = stdin();
let mut input = Input::new(BufReader::new(input.lock()));
let test_cases = input.line().next();
for _ in 0..test_cases {
let (n, k) = input.line().pair();
let mut best = 0;
for _ in 0..n {
let mut line = input.line();
let sum = (0..k).map(|_| line.next()).sum();
if sum > best {
best = sum;
}
}
println!("{}", best);
}
Ok(())
}
I find that this makes it easier to use. The example above goes through a number of test cases and for each test case it sums each line and prints the largest sum.