Home: Perl Programming Help: Regular Expressions:
trying to input chemical element and get back weight



yatinhat
Novice

Nov 4, 2004, 12:01 AM


Views: 16128
trying to input chemical element and get back weight

I am trying to do a program whereby the user inputs a chemical abbreviation, and gets the atomic weight back. I am learning and teaching myself perl. Any input apreciated.
_________________________________________

#!/usr/bin/perl

use strict;
use warnings;

print "Enter a chemical element abbreviation, or type quit";
my $line = <STDIN>;
chomp ($line);
my @Formula;
my ($weight, $string, $moleweight);

while ($line = <>)
{
chomp($line)
@Fields = split /, /, $line;

$weights {$symbol} = $weight;

$string = CO2;

@Formula = $string =~ /[A-Z][a-z]? | \d+ /g;

$moleweight = getweight (@Formula);


sub getweight
{my @Form = @_;
return $weight;
}


davorg
Thaumaturge / Moderator

Nov 4, 2004, 2:24 AM


Views: 16126
Re: [yatinhat] trying to input chemical element and get back weight

Can you give examples of the input you're expecting, the results you want and how you calculate the results.

Bear in mind that it's a long time since some of us studied any chemistry.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


yatinhat
Novice

Nov 4, 2004, 9:38 AM


Views: 16123
Re: [yatinhat] trying to input chemical element and get back weight

Periodic table elements are entered by the usr and are expected, to start with an upper case letter followed by zero or more lower case letters or numbers.

Here is what the data file looks like:

Actinium,Ac,227.00
Aluminium,Al,26.98
Americium,Am,243.00
Antimony,Sb,121.76
Argon,Ar,39.95
Arsenic,As,74.92
Astatine,At,210.00
Barium,Ba,137.33
Berkelium,Bk,247.00
Beryllium,Be,9.01
Bismuth,Bi,208.98
Bohrium,Bh,264.00
Boron,B,10.81
Bromine,Br,79.90
Cadmium,Cd,112.41
Caesium,Cs,132.91
Calcium,Ca,40.08
Californium,Cf,251.00
Carbon,C,12.01
Cerium,Ce,140.12
Chlorine,Cl,35.45
Chromium,Cr,51.99
Cobalt,Co,58.93
Copper,Cu,63.55
Curium,Cm,247.00
Dubnium,Db,262.00
Dysprosium,Dy,162.50
Einsteinium,Es,252.00
Erbium,Er,167.26
Europium,Eu,151.96
Fermium,Fm,257.00
Fluorine,F,18.99
Francium,Fr,223.00
Gadolinium,Gd,157.25
Gallium,Ga,69.72
Germanium,Ge,72.61
Gold,Au,196.97
Hafnium,Hf,178.49
Hassium,Hs,256.00
Helium,He,4.00
Holmium,Ho,164.93
Hydrogen,H,1.01
Indium,In,114.82
Iodine,I,126.90
Iridium,Ir,192.22
Iron,Fe,55.85
Krypton,Kr,83.80
Lanthanum,La,138.91
Lawrencium,Lr,262.00
Lead,Pb,207.20
Lithium,Li,6.94
Lutetium,Lu,174.97
Magnesium,Mg,24.31
Manganese,Mn,54.94
Meitnerium,Mt,268.00
Mendelevium,Md,258.00
Mercury,Hg,200.59
Molybdenum,Mo,95.94
Neodymium,Nd,144.24
Neon,Ne,20.18
Neptunium,Np,237.00
Nickel,Ni,58.69
Niobium,Nb,92.91
Nitrogen,N,14.01
Nobelium,No,259.00
Osmium,Os,190.23
Oxygen,O,15.99
Palladium,Pd,106.42
Phosphorus,P,30.98
Platinum,Pt,195.08
Plutonium,Pu,244.00
Polonium,Po,209.00
Potassium,K,39.09
Praseodymium,Pr,140.91
Promethium,Pm,145.00
Protactinium,Pa,231.04
Radium,Ra,226.00
Radon,Rn,222.00
Rhenium,Re,186.21
Rhodium,Rh,102.91
Rubidium,Rb,85.47
Ruthenium,Ru,101.07
Rutherfordium,Rf,261.00
Samarium,Sm,150.36
Scandium,Sc,44.96
Seaborgium,Sg,263.00
Selenium,Se,78.96
Silicon,Si,28.09
Silver,Ag,107.87
Sodium,Na,22.99
Strontium,Sr,87.62
Sulfur,S,32.07
Tantalum,Ta,180.95
Technetium,Tc,98.00
Tellurium,Te,127.60
Terbium,Tb,158.93
Thallium,Tl,204.38
Thorium,Th,232.04
Thulium,Tm,168.93
Tin,Sn,118.71
Titanium,Ti,47.87
Tungsten,W,183.84
Uranium,U,238.03
Vanadium,V,50.94
Xenon,Xe,131.29
Ytterbium,Yb,173.04
Yttrium,Y,88.91
Zinc,Zn,65.39
Zirconium,Zr,91.22


davorg
Thaumaturge / Moderator

Nov 5, 2004, 1:36 AM


Views: 16099
Re: [yatinhat] trying to input chemical element and get back weight

I said "Can you give examples of the input you're expecting, the results you want and how you calculate the results" and you don't seem to have addressed that at all :)

Here's the kind of explaination that I expecting to see (trying to remember the chemistry I studied 25 years ago).

User inputs a chemical formula, e.g. H20.

This is split into elements and numbers, e.g. H, 2, 0. An element name is a capital letter followed by an optional lower case letter. An optional integer follows each element name. A missing integer is assumed to be 1.

A molecule's weight is then calculated by looking up the weights of the individual elements in the attached table, multiplying by the integer from the formula and summing all these weights.

For example in H20, the weight of oxygen (O) is 15.99 and the weight of hydrogen (H) is 1.01. The total weight is therefore 2 * 1.01 + 15.99 = 18.01.

Does that accurately reflect your requirements?

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


ShipOfFools
Novice

Nov 5, 2004, 6:35 AM


Views: 16093
Re: [yatinhat] trying to input chemical element and get back weight

Assuming all the records in the file are unique constants, and the file will only be updated when new elements are discovered, wouldn't it be better to place the data in memory along with your program? Then you wouldn't have to open/lock/read/search/close the file from disk. You can just jump straight to it using the user input.


Code
 my %chemElements = qw( Cobalt 58.93 Co 58.93 Copper 63.55 Cu 63.55 Curium 247 Cm 247 ); 
print "$chemElements{$ARGV[0]}\n";



where $ARGV[0] is a chemical name or symbol.

Otherwise if your file will be modified in such a way to make the size unacceptable to memory, you could do something like this...


Code
my $file = 'PATH\TO\data.txt';  

open FILE, "$file" or die "Can't open file for read. $!\n";
flock FILE, 1;
while( <FILE> )
{
my @members = split ',';
if( $members[0] eq $ARGV[0] || $members[1] eq $ARGV[0] )
{
print "$members[2]\n";
last;
}
}
close FILE;



Dave


yatinhat
Novice

Nov 5, 2004, 8:02 AM


Views: 16087
Re: [davorg] trying to input chemical element and get back weight

Yes, that accurately describes my programs requirements. I studied chemistry in high school.

I have discovered OptiPerl program and downloaded the free trial. Is this a good program for novices?

Thanks,
Mary


davorg
Thaumaturge / Moderator

Nov 5, 2004, 9:01 AM


Views: 16081
Re: [yatinhat] trying to input chemical element and get back weight

My solution is listed below. Assuming it's in a file called "chem", you run it like this:

Code
$ ./chem H2O 
H2O = 18.01
$ ./chem H2O H2SO4
H2O = 18.01
H2SO4 = 98.05
$ ./chem H2O H2SO4 HCl
H2O = 18.01
H2SO4 = 98.05
HCl = 36.46

I've never heard of OptiPerl so I can't say how good it is.

My program...

Code
#!/usr/bin/perl 

use strict;
use warnings;

my %chem;
while (<DATA>) {
chomp;
my ($n, $s, $w) = split /,/;
$chem{$s} = $w;
}

foreach (@ARGV) {
my $weight = 0;
my @parts = /([A-Z][a-z]?)(\d*)/g;

while (my ($elem, $num) = splice @parts, 0, 2) {
next unless $chem{$elem};
$num ||= 1;

$weight += $chem{$elem} * $num;
}
print "$_ = $weight\n";
}

__END__
Actinium,Ac,227.00
Aluminium,Al,26.98
Americium,Am,243.00
Antimony,Sb,121.76
Argon,Ar,39.95
Arsenic,As,74.92
Astatine,At,210.00
Barium,Ba,137.33
Berkelium,Bk,247.00
Beryllium,Be,9.01
Bismuth,Bi,208.98
Bohrium,Bh,264.00
Boron,B,10.81
Bromine,Br,79.90
...etc...


--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks


yatinhat
Novice

Nov 8, 2004, 10:48 AM


Views: 16062
Re: [yatinhat] trying to input chemical element and get back weight

Thank you so much for your help and feedback. I am a novice Perl Programmer.

I find this block of code confusing...

while (my ($elem, $num) = splice @parts, 0, 2) {
next unless $chem{$elem};
$num ||= 1;


davorg
Thaumaturge / Moderator

Nov 9, 2004, 1:36 AM


Views: 16052
Re: [yatinhat] trying to input chemical element and get back weight


In Reply To
I find this block of code confusing...

Code
while (my ($elem, $num) = splice @parts, 0, 2) {


This uses the "splice" function to pull elements from @parts two at a time. You can read the docs for splice by typing "perldoc -f splice" at your command line.


In Reply To

Code
next unless $chem{$elem};


$elem contains the next chemical element from the formula. %chem contains a table of elements togther with their atomic weight. If $elem isn't found as a key in %chem then it's not a real chemical element and we ignore it. We use "next" to skip to the next iteration of the innermost loop.


In Reply To

Code
$num ||= 1;


If the chemical symbol didn't have an integer after it then we need to treat it as 1. If the integer is missing then $num will contain the special value "undef" which evaluates as false. This code basically says that if $num doesn't contain a value(*) then set it to 1.

(*) To be picky, it actually says, if $num doesn't contain a _true_ value - so if $num contains a zero, it will also be set to 1. But I think that's probably the correct behaviour in this case.

--
Dave Cross, Perl Hacker, Trainer and Writer
http://www.dave.org.uk/
Get more help at Perl Monks