grades.rs in Rust
A gradebook: structs, a HashMap of results, and a formatted report.
use std::collections::HashMap;
struct Student {
name: String,
marks: Vec<u32>,
}
impl Student {
fn new(name: &str, marks: &[u32]) -> Self {
Student {
name: name.to_string(),
marks: marks.to_vec(),
}
}
fn average(&self) -> f64 {
if self.marks.is_empty() {
return 0.0;
}
self.marks.iter().sum::<u32>() as f64 / self.marks.len() as f64
}
fn grade(&self) -> char {
match self.average() as u32 {
90..=100 => 'A',
80..=89 => 'B',
70..=79 => 'C',
_ => 'D',
}
}
}
fn main() {
let students = vec![
Student::new("ada", &[95, 91, 88]),
Student::new("grace", &[78, 84, 80]),
Student::new("alan", &[65, 72, 70]),
];
println!("{:<8}{:>8}{:>7}", "name", "average", "grade");
for s in &students {
println!("{:<8}{:>8.1}{:>7}", s.name, s.average(), s.grade());
}
let mut by_grade: HashMap<char, Vec<&str>> = HashMap::new();
for s in &students {
by_grade.entry(s.grade()).or_default().push(&s.name);
}
let mut grades: Vec<&char> = by_grade.keys().collect();
grades.sort();
for g in grades {
println!("{g}: {:?}", by_grade[g]);
}
let best = students
.iter()
.max_by(|a, b| a.average().partial_cmp(&b.average()).unwrap());
if let Some(top) = best {
println!("top of the class: {}", top.name);
}
}
How it works
- Each student's marks are collected into one owned record.
- The averages are computed with iterator arithmetic.
- The report uses format widths to line the columns up.
Keywords and builtins used here
HashMapSelfSomeStringStudentVecasaveragecharf64fnforgradeifimplinletmainmarksmatchmutnamenewreturnselfstrstructu32use
The run, in numbers
- Lines
- 62
- Characters to type
- 1185
- Tokens
- 430
- Three-star pace
- 100 tpm
At the three-star pace of 100 tokens a minute, this run takes about 258 seconds.
Step 2 of 2 in Encore, step 39 of 39 in Language basics.