Created
December 19, 2013 05:28
-
-
Save DeanMarkTaylor/8034827 to your computer and use it in GitHub Desktop.
Expanding Chemical Equations - my answer to StackOverflow question: http://stackoverflow.com/questions/20670653/php-function-to-expand-chemical-equations
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class chem_expand { | |
protected $multiplier; | |
function compute_bracketed_replacement( $groups ) { | |
// In-case if invalid input, output "<error>" in string. | |
$result = '<error>'; | |
// If we have "(Chem)Multiplier" | |
if ( !empty( $groups[1] ) && !empty( $groups[2] ) ) { | |
// Keep multiplier | |
$this->multiplier = intval( $groups[2] ); | |
// Look for "Chem" Or "ChemCount". | |
$result = preg_replace_callback( '/([A-Z][a-z]*)(\d+)?/mx', | |
array( $this, 'multiply_digits_replacement' ), $groups[1] ); | |
} elseif ( !empty( $groups[3] ) ) { | |
// Just plain bracketed "(anything here)". | |
$result = $groups[3]; | |
} | |
return $result; | |
} | |
function multiply_digits_replacement( $groups ) { | |
// "Chem" | |
$result = $groups[1]; | |
// Assume only one. | |
$count = 1; | |
// Count. | |
if ( !empty( $groups[2] ) ) { | |
$count = intval( $groups[2] ); | |
} | |
// Multiply the count out. | |
$count = ( $count * $this->multiplier ); | |
if ( $count > 1 ) { | |
// More than one, need the new count in the string. | |
$result = $result . $count; | |
} | |
return $result; | |
} | |
function test() { | |
echo '<p>starting test</p>'; | |
$test_values = array( | |
'(NH4)3' => 'N3H12', | |
'(Mo3O10)4' => 'Mo12O40', | |
'(NH4)3(P(Mo3O10)4)' => 'N3H12PMo12O40', | |
'H((O)2)2' => 'HO4' | |
); | |
foreach ( $test_values as $input => $expected ) { | |
$actual = $this->expand( $input ); | |
if ( $actual !== $expected ) { | |
echo '<p>failure</p>'; | |
echo '<p>Actual: \"' . $actual . '"</p>'; | |
echo '<p>Expected: \"' . $expected . '"</p>'; | |
return; | |
} | |
} | |
echo '<p>success</p>'; | |
} | |
function expand( $subject ) { | |
// Expand the inner brackets first. | |
// Loop through all the inner "(Formula)Multiplier" first, then simple bracketed "(anything)". | |
$output = preg_replace_callback( | |
'/\( | |
((?!\()[^()]+) | |
\) | |
(\d+) | |
| | |
\( | |
((?!\()[^()]+) | |
\)/ix', | |
array( $this, 'compute_bracketed_replacement' ), $subject ); | |
// If we actually changed the content, then call ourselves again and expand the brackets further. | |
if ( $output !== $subject ) { | |
$output = $this->expand( $output ); | |
} | |
return $output; | |
} | |
} | |
$instance = new chem_expand(); | |
$instance->test(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment