1use crate::{decode_utomid, ELEMENTS};
2use std::collections::HashMap;
3
4pub fn compound_mass(arr: &[u8]) -> f64 {
7 arr.iter()
8 .map(|n| ELEMENTS.get(n).unwrap().atomic_mass)
9 .sum()
10}
11
12pub fn compound_formula(arr: &[u8]) -> String {
15 let mut counts: HashMap<u8, usize> = HashMap::new();
16 for &n in arr {
17 *counts.entry(n).or_default() += 1;
18 }
19 let mut parts: Vec<String> = counts
20 .into_iter()
21 .map(|(num, count)| {
22 let sym = ELEMENTS.get(&num).unwrap().symbol;
23 if count > 1 {
24 format!("{}{}", sym, count)
25 } else {
26 sym.to_string()
27 }
28 })
29 .collect();
30 parts.sort(); parts.join("")
32}
33
34#[derive(Debug, Clone)]
37pub struct CompactCompound {
38 pub pairs: Vec<(u8, u8)>, }
40
41impl CompactCompound {
42 pub fn new(pairs: Vec<(u8, u8)>) -> Self {
43 Self { pairs }
44 }
45
46 pub fn formula(&self) -> String {
48 self.pairs
49 .iter()
50 .map(|(id, count)| {
51 if let Some(el) = decode_utomid(*id) {
52 if *count > 1 {
53 format!("{}{}", el.symbol, count)
54 } else {
55 el.symbol.to_string()
56 }
57 } else {
58 "?".to_string()
59 }
60 })
61 .collect::<Vec<_>>()
62 .join("")
63 }
64
65 pub fn mass(&self) -> f64 {
67 self.pairs
68 .iter()
69 .map(|(id, count)| {
70 if let Some(el) = decode_utomid(*id) {
71 el.atomic_mass * f64::from(*count)
72 } else {
73 0.0
74 }
75 })
76 .sum()
77 }
78}
79
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 #[test]
86 fn test_compact_water() {
87 let water = CompactCompound::new(vec![(1,2), (8,1)]);
88 assert_eq!(water.formula(), "H2O");
89 assert!((water.mass() - 18.015).abs() < 0.01);
90 }
91}