I have created a website where it has two inputs one for the reactants and the other one is for products. After submitting the two strings, I want to output a balanced chemical equation between the reactants and the products.
For example if somebody inputs H2 + O2
in the reactants and H2O
in the products.. I want the result to be 2H2 + O2 -> 2H2O
.
I am doing this to improve my skills in using arrays. But now I stopped and do not know what to do to achieve what I want.
I have got it to return this array (for the product) :
[0] => 2
[1] => 2
// [0] is the H, [1] is the O.
But, when I try to input something like CH6 + CH12 it will return it this way:
[0] => 1
[1] => 6
[2] => 12
// [0] is the C, [1] is the H6, [2] is the H12
what I really want is this :
[0] => 1
[1] => 18
// [0] is the C, [1] is the H
my current code is this :
//returns H2 + H2O
$reactions = $_GET['reactions'];
//returns H2 H2O
$reactionsnospace = str_replace('+', '', $reactions);
//returns array(H2,H2O)
$reactionsarray = explode("+",$reactions);
//returns array(H2,H2,O)
$reactionsplitarray = splitAtUpperCase($reactionsnospace);
//returns the repeated number element H2 x 2 and O x 1
$reactioncountrepeatedelements = array_count_values($reactionsplitarray);
//returns the elements name with no repetition 2 and 1 ( 2 and )
$reactionkeys = array_keys($reactioncountrepeatedelements);
foreach($reactionkeys as &$item) {
$item = preg_replace('/\D/', '', $item);
if(empty($item))
{$item = "1";}
}
//returns the elements repetition number only
$reactionvalues = array_values($reactioncountrepeatedelements);
$d = array_map(function ($a1, $a2) { return $a1 * $a2; }, $reactionkeys , $reactionvalues);
print_r($d);
I need suggestions to improve my code, solution to my current problem, and a method that I can use to reach my final goal of balancing a chemical equation. Is using array a good idea to do that? is there a better way?
Read this if you do not like reading all of the above:
I have this array:
Array ( [0] => C [1] => H6 [2] => C [3] => H12 [4] => Cl2)
what I am trying to achieve is this :
Array ( [0] => C2 [1] => H18 [2] => Cl2)
Going off the last paragraph, if you just want to sum counts of the atoms, then you can use this function. The first half creates a 2 dimensional array to store each atom type and the counts, then the 2nd half sums them up and rejoins the letters to numbers.
function addAtoms($arr){
$newArr = array();
foreach($arr as $v){
//if the entire value is alpha, assign a subscript of 1
if(ctype_alpha($v)){
$newArr[$v][] = 1;
}
//if the first 2 letters are alpha, it is an atom with 2 letters
elseif(ctype_alpha(substr($v, 0, 2))){
$newArr[substr($v, 0, 2)][] = substr($v, 2);
}
//atoms with only 1 letter like H, B, N, O, F, P, S etc
else{
$newArr[substr($v, 0, 1)][] = substr($v, 1);
}
}
//Sum the values of the 2nd level array and concatenate to the key
$new2 = array();
foreach($newArr as $k => $v){
$new2[] = $k.array_sum($v);
}
return $new2;
}
Inputting:
$test = array("C", "H6" ,"C" ,"H12" ,"Cl2");
print_r(addAtoms($test));
Will give you the desired array of:
Array ( [0] => C2 [1] => H18 [2] => Cl2 )
Edit
if you had possibly more than 1 or 2 characters, you could replace the:
//if the first 2 letters are alpha, it is an atom with 2 letters
elseif(ctype_alpha(substr($v, 0, 2))){
$newArr[substr($v, 0, 2)][] = substr($v, 2);
}
//atoms with only 1 letter like H, B, N, O, F, P, S etc
else{
$newArr[substr($v, 0, 1)][] = substr($v, 1);
}
with the less specific:
else{
$newArr[str_replace(range(0,9),'',$v)][]
= str_ireplace(range('a','z'),'',$v);
}