Premise
At to date, HackerRank does not give you anything more than a Write you code here. If you take into account that the version of the compiler is a bit old, it is a bit slow to compile, no completion or rustfmt… It is not exactly a pleasure to code in Rust on HackerRank.
So… let’s open your favorite IDE/Editor on steroids and copy-paste your solution to HR! You can also try The Rust Playground! :wink:
A starting point
Maybe the empty prompt is a bit… too empty. Here something better:
1
2
3
4
5
6
7
8
|
fn main() {
use std::io;
let stdin = io::stdin();
let mut stdin_lock = stdin.lock();
// Play with your `stdin_lock`!
}
|
Reading an array of N elements
A classic: the first line contains N
, the number of elements. The next line contains N
space-separated integers.
Let’s try the easy way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
fn main() {
use std::io::{self, BufRead};
let stdin = io::stdin();
let mut lines = stdin.lock().lines().map(Result::unwrap);
let n_elements: usize = lines.next().unwrap().parse().unwrap();
let elements: Vec<i32> = lines
.next()
.unwrap()
.split(' ')
.map(|x| x.parse().unwrap())
.collect();
assert_eq!(n_elements, elements.len());
}
|
Ouch! In real-life problems, Rust’s explicit error handling is awesome, but in this case it is just cumbersome.
We can write down a small set of utility functions, that can help us in many HR exercises. Here a practical example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
use std::{fmt::Debug, iter::FromIterator, str::FromStr};
fn parse_line_into<T, L>(lines: &mut L) -> T
where
L: Iterator<Item = String>,
T: FromStr,
<T as FromStr>::Err: Debug,
{
lines.next().unwrap().parse().unwrap()
}
fn next_parsed_line<C, T, L>(lines: &mut L) -> C
where
L: Iterator<Item = String>,
C: FromIterator<T>,
T: FromStr,
<T as FromStr>::Err: Debug,
{
lines
.next()
.unwrap()
.split(' ')
.map(|x| x.parse().unwrap())
.collect()
}
|
It is a bit of boilerplate, but it can be easily reusable. And the main becomes cleaner:
1
2
3
4
5
6
7
8
9
10
11
12
|
fn main() {
use std::io::{self, BufRead};
let stdin = io::stdin();
let mut lines = stdin.lock().lines().map(Result::unwrap);
let n_elements: usize = parse_line_into(&mut lines);
let elements: Vec<i32> = next_parsed_line(&mut lines);
assert_eq!(n_elements, elements.len());
// Use elements!
}
|
Collect all the things!!!
Remember that most of the time collect
is your friend! Do you need to collect numbers in a BTreeSet
?
1
|
let elements: BTreeSet<i32> = next_parsed_line(&mut lines);
|
Easy!!!
Output
In Rust, printing is pretty easy thanks to println!
macro:
1
2
3
4
|
println!("This is a string: {}", the_string);
println!("This is a vector, debug style: {:?}", the_vec);
println!("This is a pretty printed vector: {:#?}", the_vec);
println!("This is a float with 16 precision digits: {:.16}", the_float);
|