Background
I written a chemical equation balancing program.
elem=Alternatives@@Reverse@SortBy[StringLength]@Array[ElementData[#,"Symbol"]&,112]; chem=StringCases[#,e:elem~~n:DigitCharacter...:>{e,n}]/.""->"1"&; group=List@@@Normal[GroupBy[#,First->Last,Total@ToExpression[#]&]]&; name2mat=group/@chem[ToString/@#]&; ChemicalSolver[input_List]:=Block[{all,elemts,null}, all=name2mat[input]; elemts=Union[First@Transpose[Flatten[all,1]]]; null=NullSpace@Transpose[(elemts/.Rule@@@#&/@all)/._String->0]; Thread[input->Transpose@null] ];
Give a chemical equation:
$ $ C_2H_5OH+O_2==H_2O+CO_2$ $
The first part name2mat
change the chemicals to lists, then ChemicalSolver
calculate the nullspace and find the solution.
So one of the solutions is :
$ $ C_2H_5OH+3O_2==3H_2O+2CO_2$ $
Problems
But there are some flaws, firstly it can’t recognize the brackets, like Al2(CO3)3
.
Secondly can’t recognize the non-existent element, (These symbols not in ElementData
), a symbol like Abcd
also can be a kind of element. Some times they’ll use abbreviations in organic chemistry.
※ Thirdly can’t recognize the ion reactions like "(CO3)2-"
, this maybe hard, it’s {{"C", 1}, {"O", 3}, {"e", -2}}
, this is not necessary. ChemicalSolver
still works on this case I think.
※ Small problem, ChemicalSolver
can’t recognize reactant. Output of NullSpace
‘s positive and negative looks random.
Goal
A function expr2mat
overcome these shortcomings.
Input:
input="C2H5OH+O2=H2O+CO2" expr2mat[input]
Output:
{{{"C",2},{"H",6},{"O",1}},{{"H",2},{"O",1}},{{"O",2}},{{"C",1},{"O",2}}}