From 1ac772400a6a3aea8d006ac46337440600017e4b Mon Sep 17 00:00:00 2001 From: Igor Pashev Date: Tue, 13 Dec 2022 21:26:42 +0200 Subject: Add Rust --- Makefile | 7 ++++ mendeleev.rs | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 mendeleev.rs diff --git a/Makefile b/Makefile index 49a7570..d5399b9 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ BINARIES := \ mendeleev-f \ mendeleev-hs \ mendeleev-py \ + mendeleev-rs \ LISP := \ clisp:mendeleev.lisp \ @@ -122,3 +123,9 @@ prof-mendeleev-py.txt: prof-mendeleev-py.dat python3 -c 'import pstats; pstats.Stats("$<").sort_stats("tottime").print_stats()' > $@ +# Rust +RUSTC = rustc +RUSTC_FLAGS = -C opt-level=2 -C strip=symbols +mendeleev-rs: mendeleev.rs + $(RUSTC) $(RUSTC_FLAGS) $< -o $@ + diff --git a/mendeleev.rs b/mendeleev.rs new file mode 100644 index 0000000..af74b43 --- /dev/null +++ b/mendeleev.rs @@ -0,0 +1,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>, +} + +fn search(range: &mut Range, 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 { + 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 { + 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, formula: &mut Vec) { + 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())); + } + } +} -- cgit v1.2.3