note
space_monk
I'm sure it's been done before in the other answers, and maybe even more efficiently, but this is what I think you're trying to get to:
<code>
#!/bin/perl
#if your program doesn't begin with this, you deserve to fail...
use strict;
# Data::Dumper not used in example,
# but you always need it when you expand the module :-)
use Data::Dumper;
# you can either hardcode all atomic weights in ...
# ..or read them from a data file/ database
my %weights = (
'C' => 12.0,
'O' => 16.0,
'Co' => 58.933195,
'H' => 1.008
);
my @test = ( 'C12H22O11' );
for my $form (@test) {
my @array = $form =~ /[A-Z][a-z]*\d*/ig;
my $weight = getweight(@array);
print "Weight of @array : $weight\n";
}
sub getweight {
my @atoms =@_;
my $weight = 0.0;
for my $element (@atoms) {
if ($element =~ /([A-Z][a-z]*)(\d*)/) {
my $eweight = $weights{$1};
my $mult = $2 || 1;
$weight += ($eweight*$mult);
print STDERR "Adding $1 ($eweight)* $mult\n";
}
}
print STDERR "Molecule: @atoms\n";
return $weight;
}
</code>
<p>Feel free to modify for your purposes and correct naming,read atomic weights from a file etc.</p>
<p>Output from above program:</p>
<code>Adding C (12)* 12
Adding H (1.008)* 22
Adding O (16)* 11
Molecule: C12 H22 O11
Weight of C12 H22 O11 : 342.176
</code>
Updated to reflect the fact that some transuranic elements have 3 letter identifiers, not just two. :-)
<p>Also updated to reflect suggestions by [Kenosis] and others below....
<p>Whilst adequate for the indicated input, the method of parsing and atomic weight calculation is a little lightweight and basic, and doesn't handle more complex molecules, so consider using [mod://Chemistry::Mol] or a similar package if you want to get round the flaws that have been indicated below....</p>
<!-- Node text goes above. Div tags should contain sig only -->
<div class="pmsig"><div class="pmsig-880879">
A Monk aims to give answers to those who have none, and to learn from those who know more.
</div></div>
1006165
1006165