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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::molecule::Molecule;
use std::collections::HashMap;
use std::iter::IntoIterator;
fn get_reduced_symbols<'a, I>(symbols: I) -> HashMap<String, usize>
where
I: IntoIterator,
I::Item: std::fmt::Display,
{
let symbols: Vec<_> = symbols
.into_iter()
.map(|item| format!("{:}", item))
.collect();
let mut counts = HashMap::new();
for x in symbols {
let c = counts.entry(x).or_insert(0);
*c += 1;
}
counts
}
fn get_reduced_formula<'a, I>(symbols: I) -> String
where
I: IntoIterator,
I::Item: std::fmt::Display,
{
let counts = get_reduced_symbols(symbols);
let mut syms: Vec<String> = Vec::new();
let mut to_append = String::new();
for (k, v) in counts {
let mut s = String::new();
if v > 1 {
s = v.to_string();
}
let reduced = format!("{}{}", k, s);
if k == "C" {
syms.insert(0, reduced);
} else if k == "H" {
to_append = reduced;
} else {
syms.push(reduced);
}
}
syms.push(to_append);
let formula = syms.join("");
formula
}
#[test]
fn test_formula() {
let symbols = vec!["C", "H", "C", "H", "H", "H"];
let formula = get_reduced_formula(&symbols);
assert_eq!("C2H4", formula);
let symbols = vec!["C", "H", "C", "H", "H", "O", "H", "O"];
let formula = get_reduced_formula(&symbols);
assert_eq!("C2O2H4", formula);
}
impl Molecule {
pub fn formula(&self) -> String {
get_reduced_formula(self.symbols())
}
pub fn reduced_symbols(&self) -> HashMap<String, usize> {
get_reduced_symbols(self.symbols())
}
}