Skip to content

Instantly share code, notes, and snippets.

@DeanMarkTaylor
Created December 19, 2013 05:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DeanMarkTaylor/8034827 to your computer and use it in GitHub Desktop.
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
<?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