Chemical calculator: Difference between revisions
m (→{{header|zkl}}: piddle on my shoe) |
|||
Line 335: | Line 335: | ||
COOH(C(CH3)2)3CH3 -> 186.29499999999996 |
COOH(C(CH3)2)3CH3 -> 186.29499999999996 |
||
</pre> |
</pre> |
||
=={{header|Julia}}== |
|||
Note that Julia's 64-bit floating point gets a slightly different result for one of the assertions, hence a small change in the last example. |
|||
<lang julia>const H = 1.008 |
|||
const He = 4.002602 |
|||
const Li = 6.94 |
|||
const Be = 9.0121831 |
|||
const B = 10.81 |
|||
const C = 12.011 |
|||
const N = 14.007 |
|||
const O = 15.999 |
|||
const F = 18.998403163 |
|||
const Ne = 20.1797 |
|||
const Na = 22.98976928 |
|||
const Mg = 24.305 |
|||
const Al = 26.9815385 |
|||
const Si = 28.085 |
|||
const P = 30.973761998 |
|||
const S = 32.06 |
|||
const Cl = 35.45 |
|||
const Ar = 39.948 |
|||
const K = 39.0983 |
|||
const Ca = 40.078 |
|||
const Sc = 44.955908 |
|||
const Ti = 47.867 |
|||
const V = 50.9415 |
|||
const Cr = 51.9961 |
|||
const Mn = 54.938044 |
|||
const Fe = 55.845 |
|||
const Co = 58.933194 |
|||
const Ni = 58.6934 |
|||
const Cu = 63.546 |
|||
const Zn = 65.38 |
|||
const Ga = 69.723 |
|||
const Ge = 72.630 |
|||
const As = 74.921595 |
|||
const Se = 78.971 |
|||
const Br = 79.904 |
|||
const Kr = 83.798 |
|||
const Rb = 85.4678 |
|||
const Sr = 87.62 |
|||
const Y = 88.90584 |
|||
const Zr = 91.224 |
|||
const Nb = 92.90637 |
|||
const Mo = 95.95 |
|||
const Ru = 101.07 |
|||
const Rh = 102.90550 |
|||
const Pd = 106.42 |
|||
const Ag = 107.8682 |
|||
const Cd = 112.414 |
|||
const In = 114.818 |
|||
const Sn = 118.710 |
|||
const Sb = 121.760 |
|||
const Te = 127.60 |
|||
const I = 126.90447 |
|||
const Xe = 131.293 |
|||
const Cs = 132.90545196 |
|||
const Ba = 137.327 |
|||
const La = 138.90547 |
|||
const Ce = 140.116 |
|||
const Pr = 140.90766 |
|||
const Nd = 144.242 |
|||
const Pm = 145 |
|||
const Sm = 150.36 |
|||
const Eu = 151.964 |
|||
const Gd = 157.25 |
|||
const Tb = 158.92535 |
|||
const Dy = 162.500 |
|||
const Ho = 164.93033 |
|||
const Er = 167.259 |
|||
const Tm = 168.93422 |
|||
const Yb = 173.054 |
|||
const Lu = 174.9668 |
|||
const Hf = 178.49 |
|||
const Ta = 180.94788 |
|||
const W = 183.84 |
|||
const Re = 186.207 |
|||
const Os = 190.23 |
|||
const Ir = 192.217 |
|||
const Pt = 195.084 |
|||
const Au = 196.966569 |
|||
const Hg = 200.592 |
|||
const Tl = 204.38 |
|||
const Pb = 207.2 |
|||
const Bi = 208.98040 |
|||
const Po = 209 |
|||
const At = 210 |
|||
const Rn = 222 |
|||
const Fr = 223 |
|||
const Ra = 226 |
|||
const Ac = 227 |
|||
const Th = 232.0377 |
|||
const Pa = 231.03588 |
|||
const U = 238.02891 |
|||
const Np = 237 |
|||
const Pu = 244 |
|||
const Am = 243 |
|||
const Cm = 247 |
|||
const Bk = 247 |
|||
const Cf = 251 |
|||
const Es = 252 |
|||
const Fm = 257 |
|||
function molar_mass(s) |
|||
s = replace(s, r"\d+" => (x) -> "*" * x) |
|||
s = replace(s, r"[A-Z][a-z]{0,2}|\(" => (x) ->"+" * x) |
|||
eval(Meta.parse(s)) |
|||
end |
|||
@assert 1.008 == molar_mass("H") |
|||
@assert 2.016 == molar_mass("H2") |
|||
@assert 18.015 == molar_mass("H2O") |
|||
@assert 142.03553856000002 == molar_mass("Na2SO4") |
|||
@assert 84.162 == molar_mass("C6H12") |
|||
@assert 186.29500000000002 == molar_mass("COOH(C(CH3)2)3CH3") |
|||
</lang> |
|||
No assertion errors. |
|||
=={{header|Python}}== |
=={{header|Python}}== |
Revision as of 02:50, 19 March 2019
This application calculates the molar mass given the molecule's chemical formula.
- Introduction
- A molecule consists of atoms. E.g. water, H2O has two hydrogen atoms and one oxygen atom
- The mass of water, H2O is 1.008 * 2 + 15.999 = 18.015
- An atom name consists of one upper-case letter followed by zero or one lower-case letter.
- H (Hydrogen)
- He (Helium)
- In the future one more lower-case letter might be used.
- Uue (Ununennium)
- Ubn (Unbinilium)
- The number of atoms is stated behind the atom or atom group
- An atom group is specified using parenthesis. E.g. Butyric acid, (CH3)2CHCOOH, has two CH3 groups
- A group may contain other groups, e.g. COOH(C(CH3)2)3CH3
- The atom masses are available in the Python section below
- Background
- The mass is dimensionless. It is relative to 1/12 of Carbon-12
- Carbon-12 has exactly 12 protons, 12 electrons and 12 neutrons
- One mole of H2O has the mass 18.015 grams
- One mole is 6.02214076E23
- Examples
<lang python>assert 1.008 == molar_mass('H') assert 2.016 == molar_mass('H2') assert 18.015 == molar_mass('H2O') assert 142.03553856000002 == molar_mass('Na2SO4') assert 84.162 == molar_mass('C6H12') assert 186.29499999999996 == molar_mass('COOH(C(CH3)2)3CH3')</lang>
- Link
https://en.wikipedia.org/wiki/Molecular_mass
Go
<lang go>package main
import (
"fmt" "strconv" "strings"
)
type any = interface{}
type ht = map[string]int
type Stack []any
func (s *Stack) push(a any) {
*s = append(*s, a)
}
func (s *Stack) pop() any {
le := len(*s) if le == 0 { panic("Attempt to pop from an empty stack") } le-- a := (*s)[le] *s = (*s)[:le] return a
}
var atomicMass = map[string]float64{
"H": 1.008, "He": 4.002602, "Li": 6.94, "Be": 9.0121831, "B": 10.81, "C": 12.011, "N": 14.007, "O": 15.999, "F": 18.998403163, "Ne": 20.1797, "Na": 22.98976928, "Mg": 24.305, "Al": 26.9815385, "Si": 28.085, "P": 30.973761998, "S": 32.06, "Cl": 35.45, "Ar": 39.948, "K": 39.0983, "Ca": 40.078, "Sc": 44.955908, "Ti": 47.867, "V": 50.9415, "Cr": 51.9961, "Mn": 54.938044, "Fe": 55.845, "Co": 58.933194, "Ni": 58.6934, "Cu": 63.546, "Zn": 65.38, "Ga": 69.723, "Ge": 72.630, "As": 74.921595, "Se": 78.971, "Br": 79.904, "Kr": 83.798, "Rb": 85.4678, "Sr": 87.62, "Y": 88.90584, "Zr": 91.224, "Nb": 92.90637, "Mo": 95.95, "Ru": 101.07, "Rh": 102.90550, "Pd": 106.42, "Ag": 107.8682, "Cd": 112.414, "In": 114.818, "Sn": 118.710, "Sb": 121.760, "Te": 127.60, "I": 126.90447, "Xe": 131.293, "Cs": 132.90545196, "Ba": 137.327, "La": 138.90547, "Ce": 140.116, "Pr": 140.90766, "Nd": 144.242, "Pm": 145, "Sm": 150.36, "Eu": 151.964, "Gd": 157.25, "Tb": 158.92535, "Dy": 162.500, "Ho": 164.93033, "Er": 167.259, "Tm": 168.93422, "Yb": 173.054, "Lu": 174.9668, "Hf": 178.49, "Ta": 180.94788, "W": 183.84, "Re": 186.207, "Os": 190.23, "Ir": 192.217, "Pt": 195.084, "Au": 196.966569, "Hg": 200.592, "Tl": 204.38, "Pb": 207.2, "Bi": 208.98040, "Po": 209, "At": 210, "Rn": 222, "Fr": 223, "Ra": 226, "Ac": 227, "Th": 232.0377, "Pa": 231.03588, "U": 238.02891, "Np": 237, "Pu": 244, "Am": 243, "Cm": 247, "Bk": 247, "Cf": 251, "Es": 252, "Fm": 257,
}
// "H2O" => H 2 O func parse(s string) (result []string, pattern string) {
for i := 0; i < len(s); { switch { case s[i] >= 'A' && s[i] <= 'Z': if i+1 < len(s) && s[i+1] >= 'a' && s[i+1] <= 'z' { result = append(result, fmt.Sprintf("%c%c", s[i], s[i+1])) pattern += "A" i += 2 } else { result = append(result, string(s[i])) pattern += "A" i++ } case s[i] >= '0' && s[i] <= '9': antal := int(s[i]) - 48 i++ for i < len(s) && s[i] >= '0' && s[i] <= '9' { antal = antal*10 + int(s[i]) - 48 i++ } result = append(result, strconv.Itoa(antal)) pattern += "1" default: result = append(result, string(s[i])) pattern += string(s[i]) i++ } } return
}
// H 2 O => H * 2 + O func pass1(m1 []string, m2 string) (result []string) {
const symbols = "A1()" matrix := [4]string{ "+*+=", // A = Atom "+x+=", // 1 = Count "=x=x", // ( "+*+=", // ) } add := func(a string) []string { return []string{a, "+"} } mul := func(a string) []string { return []string{a, "*"} } err := func(a string) []string { return []string{} } nop := func(a string) []string { return []string{a} } operation := map[byte]func(string) []string{ '+': add, '*': mul, 'x': err, '=': nop, } for i := 0; i < len(m1)-1; i++ { ch0 := m2[i] ch1 := m2[i+1] i0 := strings.IndexByte(symbols, ch0) i1 := strings.IndexByte(symbols, ch1) op := matrix[i0][i1] result = append(result, operation[op](m1[i])...) } result = append(result, m1[len(m1)-1]) return
}
// H * 2 + O => H 2 * O + func pass2(tokens []string) (result []string) {
ops := "+*" stack := new(Stack) for _, token := range tokens { switch token { case "(": stack.push(token) case ")": for len(*stack) > 0 { op := stack.pop().(string) if op == "(" { break } result = append(result, op) } default: if strings.Index(ops, token) >= 0 { for len(*stack) > 0 { op := (*stack)[len(*stack)-1].(string) if strings.Index(ops, op) == -1 { break } if strings.Index(ops, token) >= strings.Index(ops, op) { break } stack.pop() result = append(result, op) } stack.push(token) } else { result = append(result, token) } } } for len(*stack) > 0 { result = append(result, stack.pop().(string)) } return
}
// H 2 * O + => { H:2, O:1 } func pass3(rpn []string) ht {
stack := new(Stack) for _, item := range rpn { switch { case item == "+": h1 := stack.pop().(ht) h2 := (*stack)[len(*stack)-1].(ht) for key := range h1 { if h2[key] > 0 { h2[key] += h1[key] } else { h2[key] = h1[key] } } case item == "*": antal, _ := strconv.Atoi(stack.pop().(string)) hash := (*stack)[len(*stack)-1].(ht) for key := range hash { hash[key] *= antal } case atomicMass[item] > 0.0: res := make(ht) res[item] = 1 stack.push(res) default: stack.push(item) } } return stack.pop().(ht)
}
// { H:2, O:1 } => 18.015 func pass4(atoms ht) float64 {
sum := 0.0 for key := range atoms { sum += atomicMass[key] * float64(atoms[key]) } return sum
}
func molarMass(molecule string) float64 {
atomList, pattern := parse(molecule) infix := pass1(atomList, pattern) rpn := pass2(infix) atoms := pass3(rpn) return pass4(atoms)
}
func main() {
molecules := []string{"H", "H2", "H2O", "Na2SO4", "C6H12", "COOH(C(CH3)2)3CH3"} for _, molecule := range molecules { mass := molarMass(molecule) fmt.Printf("%17s -> %g\n", molecule, mass) }
}</lang>
- Output:
H -> 1.008 H2 -> 2.016 H2O -> 18.015 Na2SO4 -> 142.03553856000002 C6H12 -> 84.162 COOH(C(CH3)2)3CH3 -> 186.29499999999996
Julia
Note that Julia's 64-bit floating point gets a slightly different result for one of the assertions, hence a small change in the last example. <lang julia>const H = 1.008 const He = 4.002602 const Li = 6.94 const Be = 9.0121831 const B = 10.81 const C = 12.011 const N = 14.007 const O = 15.999 const F = 18.998403163 const Ne = 20.1797 const Na = 22.98976928 const Mg = 24.305 const Al = 26.9815385 const Si = 28.085 const P = 30.973761998 const S = 32.06 const Cl = 35.45 const Ar = 39.948 const K = 39.0983 const Ca = 40.078 const Sc = 44.955908 const Ti = 47.867 const V = 50.9415 const Cr = 51.9961 const Mn = 54.938044 const Fe = 55.845 const Co = 58.933194 const Ni = 58.6934 const Cu = 63.546 const Zn = 65.38 const Ga = 69.723 const Ge = 72.630 const As = 74.921595 const Se = 78.971 const Br = 79.904 const Kr = 83.798 const Rb = 85.4678 const Sr = 87.62 const Y = 88.90584 const Zr = 91.224 const Nb = 92.90637 const Mo = 95.95 const Ru = 101.07 const Rh = 102.90550 const Pd = 106.42 const Ag = 107.8682 const Cd = 112.414 const In = 114.818 const Sn = 118.710 const Sb = 121.760 const Te = 127.60 const I = 126.90447 const Xe = 131.293 const Cs = 132.90545196 const Ba = 137.327 const La = 138.90547 const Ce = 140.116 const Pr = 140.90766 const Nd = 144.242 const Pm = 145 const Sm = 150.36 const Eu = 151.964 const Gd = 157.25 const Tb = 158.92535 const Dy = 162.500 const Ho = 164.93033 const Er = 167.259 const Tm = 168.93422 const Yb = 173.054 const Lu = 174.9668 const Hf = 178.49 const Ta = 180.94788 const W = 183.84 const Re = 186.207 const Os = 190.23 const Ir = 192.217 const Pt = 195.084 const Au = 196.966569 const Hg = 200.592 const Tl = 204.38 const Pb = 207.2 const Bi = 208.98040 const Po = 209 const At = 210 const Rn = 222 const Fr = 223 const Ra = 226 const Ac = 227 const Th = 232.0377 const Pa = 231.03588 const U = 238.02891 const Np = 237 const Pu = 244 const Am = 243 const Cm = 247 const Bk = 247 const Cf = 251 const Es = 252 const Fm = 257
function molar_mass(s)
s = replace(s, r"\d+" => (x) -> "*" * x) s = replace(s, r"[A-Z][a-z]{0,2}|\(" => (x) ->"+" * x) eval(Meta.parse(s))
end
@assert 1.008 == molar_mass("H") @assert 2.016 == molar_mass("H2") @assert 18.015 == molar_mass("H2O") @assert 142.03553856000002 == molar_mass("Na2SO4") @assert 84.162 == molar_mass("C6H12") @assert 186.29500000000002 == molar_mass("COOH(C(CH3)2)3CH3") </lang> No assertion errors.
Python
Atom masses
<lang python>ATOMIC_MASS = { 'H':1.008, 'He':4.002602, 'Li':6.94, 'Be':9.0121831, 'B':10.81, 'C':12.011, 'N':14.007, 'O':15.999, 'F':18.998403163, 'Ne':20.1797, 'Na':22.98976928, 'Mg':24.305, 'Al':26.9815385, 'Si':28.085, 'P':30.973761998, 'S':32.06, 'Cl':35.45, 'Ar':39.948, 'K':39.0983, 'Ca':40.078, 'Sc':44.955908, 'Ti':47.867, 'V':50.9415, 'Cr':51.9961, 'Mn':54.938044, 'Fe':55.845, 'Co':58.933194, 'Ni':58.6934, 'Cu':63.546, 'Zn':65.38, 'Ga':69.723, 'Ge':72.630, 'As':74.921595, 'Se':78.971, 'Br':79.904, 'Kr':83.798, 'Rb':85.4678, 'Sr':87.62, 'Y':88.90584, 'Zr':91.224, 'Nb':92.90637, 'Mo':95.95, 'Ru':101.07, 'Rh':102.90550, 'Pd':106.42, 'Ag':107.8682, 'Cd':112.414, 'In':114.818, 'Sn':118.710, 'Sb':121.760, 'Te':127.60, 'I':126.90447, 'Xe':131.293, 'Cs':132.90545196, 'Ba':137.327, 'La':138.90547, 'Ce':140.116, 'Pr':140.90766, 'Nd':144.242, 'Pm':145, 'Sm':150.36, 'Eu':151.964, 'Gd':157.25, 'Tb':158.92535, 'Dy':162.500, 'Ho':164.93033, 'Er':167.259, 'Tm':168.93422, 'Yb':173.054, 'Lu':174.9668, 'Hf':178.49, 'Ta':180.94788, 'W':183.84, 'Re':186.207, 'Os':190.23, 'Ir':192.217, 'Pt':195.084, 'Au':196.966569, 'Hg':200.592, 'Tl':204.38, 'Pb':207.2, 'Bi':208.98040, 'Po':209, 'At':210, 'Rn':222, 'Fr':223, 'Ra':226, 'Ac':227, 'Th':232.0377, 'Pa':231.03588, 'U':238.02891, 'Np':237, 'Pu':244, 'Am':243, 'Cm':247, 'Bk':247, 'Cf':251, 'Es':252, 'Fm':257 }</lang>
Solution
<lang python>from atomic_mass import ATOMIC_MASS
def parse(s): # 'H2O' => H 2 O result = [] pattern = i = 0 while i<len(s): if s[i].isupper(): if i+1<len(s) and s[i+1].islower(): result.append(s[i]+s[i+1]) pattern += 'A' i+=2 else: result.append(s[i]) pattern += 'A' i+=1 elif s[i].isdigit(): antal = int(s[i]) i+=1 while i<len(s) and s[i].isdigit(): antal = antal*10 + int(s[i]) i+=1 result.append(str(antal)) pattern += '1' else: result.append(s[i]) pattern += s[i] i+=1 return result,pattern
def pass1(m1,m2): # H 2 O => H * 2 + O SYMBOLS = 'A1()' matrix = [ '+*+=', # A = Atom '+x+=', # 1 = Count '=x=x', # ( '+*+='] # )
result = []
add = lambda a, b: [a, '+'] mul = lambda a, b: [a, '*'] error = lambda a, b: [] nop = lambda a, b: [a] operation = {'+': add, '*': mul, 'x': error, '=': nop}
for i in range(len(m1)-1): ch0 = m2[i] ch1 = m2[i+1] i0 = SYMBOLS.index(ch0) i1 = SYMBOLS.index(ch1) op = matrix[i0][i1] result += operation[op](m1[i],m1[i+1]) result.append(m1[-1]) return result
def pass2(tokens): # H * 2 + O => H 2 * O + ops = "+*" stack = [] result = []
for token in tokens: if token == '(': stack.append(token) elif token == ')': while len(stack) > 0: op = stack.pop() if op == '(': break result.append(op) else: if token in ops: while len(stack) > 0: op = stack[-1] if not (op in ops): break if ops.find(token) >= ops.find(op): break stack.pop() result.append(op) stack.append(token) else: result.append(token)
while len(stack) > 0: result.append(stack.pop()) return result
def pass3(rpn): # H 2 * O + => { H:2, O:1 } stack = [] for item in rpn: if item == '+': h1 = stack.pop() h2 = stack[-1] for key in h1: if key in h2: h2[key] += h1[key] else: h2[key] = h1[key] elif item == '*': antal = int(stack.pop()) hash = stack[-1] for key in hash: hash[key] *= antal elif item in ATOMIC_MASS: res = {} res[item] = 1 stack.append(res) else: stack.append(item) return stack.pop()
def pass4(atoms): # { H:2, O:1 } => 18.015 return sum([ATOMIC_MASS[key] * atoms[key] for key in atoms])
def molar_mass(molecule): atom_list,pattern = parse(molecule) infix = pass1(atom_list,pattern) rpn = pass2(infix) atoms = pass3(rpn) return pass4(atoms)
#assert 'Na 10 C O O H ( C ( C H 3 ) 2 ) 3 C H 3' == ' '.join(atom_list) #assert 'A1AAAA(A(AA1)1)1AA1' == pattern #assert 'Na * 10 + C + O + O + H + ( C + ( C + H * 3 ) * 2 ) * 3 + C + H * 3' == (' '.join(infix)) #assert 'Na 10 * C O O H C C H 3 * + 2 * + 3 * C H 3 * + + + + + + +' == ' '.join(rpn) #assert {'Na':10, 'C': 11, 'O': 2, 'H': 22} == atoms
assert 1.008 == molar_mass('H') assert 2.016 == molar_mass('H2') assert 18.015 == molar_mass('H2O') assert 142.03553856000002 == molar_mass('Na2SO4') assert 84.162 == molar_mass('C6H12') assert 186.29499999999996 == molar_mass('COOH(C(CH3)2)3CH3')</lang>
zkl
<lang zkl>fcn molarMass(str,mass=0.0){
while(span:=str.span("(",")",False)){ // get inner most () group group:=str[span.xplode()]; // (CH3) str =str.del(span.xplode()); // nuke (CH3) w :=molarMass(group[1,-1],mass); // remove "(" & ")" i,s2 := span[0], str[i,*]; if(m.search(s2)) // well crap, (CH3)2 { z:=m.matched[1]; str=str.del(i,z.len()); mass=w*z.toInt() } else mass=w; } ms:=List(mass); // HO --> (1.008,15.999).sum() while(str){ nm:=atoms.filter1('wrap(a){ a.glob(str,0) }); // case matters if(not nm) // H2, didn't match 2, look for 2 now
{ m.search(str); nm=m.matched[1]; ms[-1]*=nm.toInt(); }
else ms.append(atomicMass[nm=nm[0,-1]]); // "H*"-->"H" str=str.del(0,nm.len()); // nuke H or 2 } ms.reduce('+);
}</lang> <lang zkl>var [const] atomicMass = Dictionary(
"Ac",227.000000, "Ag",107.868200, "Al", 26.981538, "Am",243.000000, "Ar", 39.948000, "As", 74.921595, "At",210.000000, "Au",196.966569, "B" , 10.810000, "Ba",137.327000, "Be", 9.012183, "Bi",208.980400, "Bk",247.000000, "Br", 79.904000, "C" , 12.011000, "Ca", 40.078000, "Cd",112.414000, "Ce",140.116000, "Cf",251.000000, "Cl", 35.450000, "Cm",247.000000, "Co", 58.933194, "Cr", 51.996100, "Cs",132.905452, "Cu", 63.546000, "Dy",162.500000, "Er",167.259000, "Es",252.000000, "Eu",151.964000, "F" , 18.998403, "Fe", 55.845000, "Fm",257.000000, "Fr",223.000000, "Ga", 69.723000, "Gd",157.250000, "Ge", 72.630000, "H" , 1.008000, "He", 4.002602, "Hf",178.490000, "Hg",200.592000, "Ho",164.930330, "I" ,126.904470, "In",114.818000, "Ir",192.217000, "K" , 39.098300, "Kr", 83.798000, "La",138.905470, "Li", 6.940000, "Lu",174.966800, "Mg", 24.305000, "Mn", 54.938044, "Mo", 95.950000, "N" , 14.007000, "Na", 22.989769, "Nb", 92.906370, "Nd",144.242000, "Ne", 20.179700, "Ni", 58.693400, "Np",237.000000, "O" , 15.999000, "Os",190.230000, "P" , 30.973762, "Pa",231.035880, "Pb",207.200000, "Pd",106.420000, "Pm",145.000000, "Po",209.000000, "Pr",140.907660, "Pt",195.084000, "Pu",244.000000, "Ra",226.000000, "Rb", 85.467800, "Re",186.207000, "Rh",102.905500, "Rn",222.000000, "Ru",101.070000, "S" , 32.060000, "Sb",121.760000, "Sc", 44.955908, "Se", 78.971000, "Si", 28.085000, "Sm",150.360000, "Sn",118.710000, "Sr", 87.620000, "Ta",180.947880, "Tb",158.925350, "Te",127.600000, "Th",232.037700, "Ti", 47.867000, "Tl",204.380000, "Tm",168.934220, "U" ,238.028910, "V" , 50.941500, "W" ,183.840000, "Xe",131.293000, "Y" , 88.905840, "Yb",173.054000, "Zn", 65.380000, "Zr", 91.224000,
), m=RegExp("([1-9]+)"),
atoms=fcn{ // sort by name length, tack on "*" so "H*" globs H2 nms:=atomicMass.keys; [(nms.apply("len") : (0).max(_)) .. 1, -1].pump(List, // 2..1 'wrap(n){ nms.filter('wrap(nm){ nm.len()==n }) }).flatten() .apply('+("*")); }(); // --> (Lu*, Es*, Er*, Eu*, ... V*, W*, Y*)</lang>
<lang zkl>foreach cstr in (T("H","H2","H2O","Na2SO4","C6H12","COOH(C(CH3)2)3CH3"))
{ println(cstr," --> ",molarMass(cstr)) }</lang>
- Output:
H --> 1.008 H2 --> 2.016 H2O --> 18.015 Na2SO4 --> 142.036 C6H12 --> 84.162 COOH(C(CH3)2)3CH3 --> 186.295