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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
use std::{collections::LinkedList, env, ops::Range, str};
#[rustfmt::skip]
static ELEMENTS : [&[u8]; 119] = [ b"?",
b"Ac", b"Ag", b"Al", b"Am", b"Ar", b"As", b"At", b"Au", b"B", b"Ba", b"Be", b"Bh",
b"Bi", b"Bk", b"Br", b"C", b"Ca", b"Cd", b"Ce", b"Cf", b"Cl", b"Cm", b"Cn", b"Co",
b"Cr", b"Cs", b"Cu", b"Db", b"Ds", b"Dy", b"Er", b"Es", b"Eu", b"F", b"Fe", b"Fl",
b"Fm", b"Fr", b"Ga", b"Gd", b"Ge", b"H", b"He", b"Hf", b"Hg", b"Ho", b"Hs", b"I",
b"In", b"Ir", b"K", b"Kr", b"La", b"Li", b"Lr", b"Lu", b"Lv", b"Mc", b"Md", b"Mg",
b"Mn", b"Mo", b"Mt", b"N", b"Na", b"Nb", b"Nd", b"Ne", b"Nh", b"Ni", b"No", b"Np",
b"O", b"Og", b"Os", b"P", b"Pa", b"Pb", b"Pd", b"Pm", b"Po", b"Pr", b"Pt", b"Pu",
b"Ra", b"Rb", b"Re", b"Rf", b"Rg", b"Rh", b"Rn", b"Ru", b"S", b"Sb", b"Sc", b"Se",
b"Sg", b"Si", b"Sm", b"Sn", b"Sr", b"Ta", b"Tb", b"Tc", b"Te", b"Th", b"Ti", b"Tl",
b"Tm", b"Ts", b"U", b"V", b"W", b"Xe", b"Y", b"Yb", b"Zn", b"Zr"
];
struct Split<'a> {
eid: usize,
tail: &'a [u8],
}
struct Element {
eid: usize,
next: Option<LinkedList<Element>>,
}
fn search(range: &mut Range<usize>, shift: usize, mut c: u8) {
let mut u = range.end;
let mut l = range.start;
c |= b' ';
while l < u {
let m = (l + u) / 2;
if (ELEMENTS[m][shift] | b' ') < c {
l = m + 1;
} else {
u = m;
}
}
if !range.contains(&l) || ((ELEMENTS[l][shift] | b' ') != c) {
range.end = 0;
return;
}
u = range.end;
range.start = l;
while l < u {
let m = (l + u) / 2;
if c < (ELEMENTS[m][shift] | b' ') {
u = m;
} else {
l = m + 1;
}
}
range.end = u;
}
fn split(tail: &[u8]) -> LinkedList<Split> {
let mut x = LinkedList::new();
let mut shift = 0;
let mut range = 1..ELEMENTS.len() - 1;
while shift < tail.len() {
search(&mut range, shift, tail[shift]);
if range.is_empty() {
break;
}
shift += 1;
if shift == ELEMENTS[range.start].len() {
x.push_back(Split {
eid: range.start,
tail: &tail[shift..],
});
range.start += 1;
}
}
if x.is_empty() {
x.push_back(Split {
eid: 0,
tail: &tail[1..],
});
}
x
}
fn explode(tail: &[u8]) -> LinkedList<Element> {
split(tail)
.into_iter()
.map(|x| Element {
eid: x.eid,
next: if x.tail.is_empty() {
None
} else {
Some(explode(x.tail))
},
})
.collect()
}
fn print_plain(tree: &LinkedList<Element>, formula: &mut Vec<usize>) {
for x in tree {
formula.push(x.eid);
if let Some(next) = &x.next {
print_plain(next, formula);
} else {
for i in formula.iter() {
print!(" {}", unsafe { str::from_utf8_unchecked(ELEMENTS[*i]) });
}
println!();
}
formula.pop();
}
}
fn main() {
for word in env::args().skip(1) {
println!("{word}:");
if !word.is_empty() {
let tail = word.as_bytes();
print_plain(&explode(tail), &mut Vec::with_capacity(tail.len()));
}
}
}
|