-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.rs
78 lines (71 loc) · 2.29 KB
/
main.rs
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
use color_eyre::eyre::{eyre, Result};
use indicatif::{ParallelProgressIterator, ProgressStyle};
use rayon::prelude::*;
const TEMPLATE: &str =
"[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} ETA {eta_precise} ({per_sec})";
#[derive(Debug, Clone, Copy)]
struct WeatherStationStatistics {
min: f64,
max: f64,
sum: f64,
count: usize,
}
impl Default for WeatherStationStatistics {
fn default() -> Self {
Self {
min: f64::INFINITY,
max: f64::NEG_INFINITY,
sum: 0.0,
count: 0,
}
}
}
fn main() -> Result<()> {
color_eyre::install()?;
let map = std::fs::read_to_string("measurements.txt")?
.lines()
.collect::<Vec<_>>()
.into_par_iter()
.progress_with_style(ProgressStyle::default_bar().template(TEMPLATE)?)
.map(|line| -> Result<_> {
let (id, measurement) = line
.split_once(';')
.ok_or_else(|| eyre!("invalid line {line:?}"))?;
Ok((id, measurement.parse::<f64>()?))
})
.try_fold_with(
rustc_hash::FxHashMap::<String, WeatherStationStatistics>::default(),
|mut acc, res| -> Result<_> {
let (id, measurement) = res?;
let stats = acc.entry(id.to_string()).or_default();
stats.min = stats.min.min(measurement);
stats.max = stats.max.max(measurement);
stats.sum += measurement;
stats.count += 1;
Ok(acc)
},
)
.try_reduce(
|| rustc_hash::FxHashMap::<String, WeatherStationStatistics>::default(),
|mut acc, map| -> Result<_> {
for (id, stats) in map {
let acc_stats = acc.entry(id).or_default();
acc_stats.min = acc_stats.min.min(stats.min);
acc_stats.max = acc_stats.max.max(stats.max);
acc_stats.sum += stats.sum;
acc_stats.count += stats.count;
}
Ok(acc)
},
)?;
for (id, stats) in map {
println!(
"{}={}/{}/{}",
id,
stats.min,
stats.max,
stats.sum / stats.count as f64
);
}
Ok(())
}