Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Replace multiple if() statements?

Status
Not open for further replies.

MonsterAar

Programmer
Aug 16, 2006
24
AU
I've written a program for calculating the molecular mass of any inputted molecule. I've constructed it using 118 if statements as you can see:

Code:
#!/usr/bin/perl -w
#perl2exe_include Math::BigInt
#perl2exe_include Math::BigInt::Calc

#molwt.pl : Calculates molecular weights
#Written by Luke Aaron
#Version B 30/01/08

use bignum;

print "\nFormat example: Water written H-2O-1\n";
print  "Enter Compound: ";
$compound = <STDIN>;
chomp($compound);

#split compound into elements
@elements = split /(?=[A-Z])/, $compound;

#find the number of elements
$elenum = $#elements;

#initialise element counter
$num = 0;
#initialise molecular weight
$molwt = 0;

#calculation loop
while(1) {
    #split element to element and number:
    @elesplit = split(/-/, $elements[$num]);
    
    #find what element it is and save atomic mass to $wt
    if($elesplit[0] eq 'H') {
        $wt = 1.00794;
    }
    if($elesplit[0] eq 'He') {
        $wt = 4.002602;
    }
    if($elesplit[0] eq 'Li') {
        $wt = 6.941;
    }
    if($elesplit[0] eq 'Be') {
        $wt = 9.012182;
    }
    if($elesplit[0] eq 'B') {
        $wt = 10.811;
    }
    if($elesplit[0] eq 'C') {
        $wt = 12.0107;
    }
    if($elesplit[0] eq 'N') {
        $wt = 14.0067;
    }
    if($elesplit[0] eq 'O') {
        $wt = 15.9994;
    }
    if($elesplit[0] eq 'F') {
        $wt = 18.9984032;
    }
    if($elesplit[0] eq 'Ne') {
        $wt = 20.1797;
    }
    if($elesplit[0] eq 'Na') {
        $wt = 22.98976928;
    }
    if($elesplit[0] eq 'Mg') {
        $wt = 24.3050;
    }
    if($elesplit[0] eq 'Al') {
        $wt = 26.9815386;
    }
    if($elesplit[0] eq 'Si') {
        $wt = 28.0855;
    }
    if($elesplit[0] eq 'P') {
        $wt = 30.973762;
    }
    if($elesplit[0] eq 'S') {
        $wt = 32.065;
    }
    if($elesplit[0] eq 'Cl') {
        $wt = 35.453;
    }
    if($elesplit[0] eq 'K') {
        $wt = 39.0983;
    }
    if($elesplit[0] eq 'Ar') {
        $wt = 39.948;
    }
    if($elesplit[0] eq 'Ca') {
        $wt = 40.078;
    }
    if($elesplit[0] eq 'Sc') {
        $wt = 44.955912;
    }
    if($elesplit[0] eq 'Ti') {
        $wt = 47.867;
    }
    if($elesplit[0] eq 'V') {
        $wt = 50.9415;
    }
    if($elesplit[0] eq 'Cr') {
        $wt = 51.9961;
    }
    if($elesplit[0] eq 'Mn') {
        $wt = 54.938045;
    }
    if($elesplit[0] eq 'Fe') {
        $wt = 55.845;
    }
    if($elesplit[0] eq 'Ni') {
        $wt = 58.6934;
    }
    if($elesplit[0] eq 'Co') {
        $wt = 58.933195;
    }
    if($elesplit[0] eq 'Cu') {
        $wt = 63.546;
    }
    if($elesplit[0] eq 'Zn') {
        $wt = 65.409;
    }
    if($elesplit[0] eq 'Ga') {
        $wt = 69.723;
    }
    if($elesplit[0] eq 'Ge') {
        $wt = 72.64;
    }
    if($elesplit[0] eq 'As') {
        $wt = 74.92160;
    }
    if($elesplit[0] eq 'Se') {
        $wt = 78.96;
    }
    if($elesplit[0] eq 'Br') {
        $wt = 79.904;
    }
    if($elesplit[0] eq 'Kr') {
        $wt = 83.798;
    }
    if($elesplit[0] eq 'Rb') {
        $wt = 85.4678;
    }
    if($elesplit[0] eq 'Sr') {
        $wt = 97.62;
    }
    if($elesplit[0] eq 'Y') {
        $wt = 88.90585;
    }
    if($elesplit[0] eq 'Zr') {
        $wt = 91.224;
    }
    if($elesplit[0] eq 'Nb') {
        $wt = 92.906;
    }
    if($elesplit[0] eq 'Mo') {
        $wt = 95.94;
    }
    if($elesplit[0] eq 'Tc') {
        $wt = 98;
    }
    if($elesplit[0] eq 'Ru') {
        $wt = 101.07;
    }
    if($elesplit[0] eq 'Rh') {
        $wt = 102.90550;
    }
    if($elesplit[0] eq 'Pd') {
        $wt = 106.42;
    }
    if($elesplit[0] eq 'Ag') {
        $wt = 107.8682;
    }
    if($elesplit[0] eq 'Cd') {
        $wt = 112.411;
    }
    if($elesplit[0] eq 'In') {
        $wt = 114.818;
    }
    if($elesplit[0] eq 'Sn') {
        $wt = 118.710;
    }
    if($elesplit[0] eq 'Sb') {
        $wt = 121.760;
    }
    if($elesplit[0] eq 'Te') {
        $wt = 127.60;
    }
    if($elesplit[0] eq 'I') {
        $wt = 126.90447;
    }
    if($elesplit[0] eq 'Xe') {
        $wt = 131.293;
    }
    if($elesplit[0] eq 'Cs') {
        $wt = 132.9054519;
    }
    if($elesplit[0] eq 'Ba') {
        $wt = 137.327;
    }
    if($elesplit[0] eq 'La') {
        $wt = 138.90547;
    }
    if($elesplit[0] eq 'Ce') {
        $wt = 140.116;
    }
    if($elesplit[0] eq 'Pr') {
        $wt = 140.90765;
    }
    if($elesplit[0] eq 'Nd') {
        $wt = 144.242;
    }
    if($elesplit[0] eq 'Pm') {
        $wt = 145;
    }
    if($elesplit[0] eq 'Sm') {
        $wt = 150.36;
    }
    if($elesplit[0] eq 'Eu') {
        $wt = 151.964;
    }
    if($elesplit[0] eq 'Gd') {
        $wt = 157.25;
    }
    if($elesplit[0] eq 'Tb') {
        $wt = 158.92535;
    }
    if($elesplit[0] eq 'Dy') {
        $wt = 162.500;
    }
    if($elesplit[0] eq 'Ho') {
        $wt = 164.930;
    }
    if($elesplit[0] eq 'Er') {
        $wt = 167.259;
    }
    if($elesplit[0] eq 'Tm') {
        $wt = 168.93421;
    }
    if($elesplit[0] eq 'Yb') {
        $wt = 173.04;
    }
    if($elesplit[0] eq 'Lu') {
        $wt = 174.967;
    }
    if($elesplit[0] eq 'Hf') {
        $wt = 178.49;
    }
    if($elesplit[0] eq 'Ta') {
        $wt = 180.94788;
    }
    if($elesplit[0] eq 'W') {
        $wt = 183.84;
    }
    if($elesplit[0] eq 'Re') {
        $wt = 186.207;
    }
    if($elesplit[0] eq 'Os') {
        $wt = 190.23;
    }
    if($elesplit[0] eq 'Ir') {
        $wt = 192.217;
    }
    if($elesplit[0] eq 'Pt') {
        $wt = 195.084;
    }
    if($elesplit[0] eq 'Au') {
        $wt = 196.966569;
    }
    if($elesplit[0] eq 'Hg') {
        $wt = 200.59;
    }
    if($elesplit[0] eq 'Tl') {
        $wt = 204.3833;
    }
    if($elesplit[0] eq 'Pb') {
        $wt = 207.2;
    }
    if($elesplit[0] eq 'Bi') {
        $wt = 208.98040;
    }
    if($elesplit[0] eq 'Po') {
        $wt = 210;
    }
    if($elesplit[0] eq 'At') {
        $wt = 210;
    }
    if($elesplit[0] eq 'Rn') {
        $wt = 220;
    }
    if($elesplit[0] eq 'Fr') {
        $wt = 223;
    }
    if($elesplit[0] eq 'Ra') {
        $wt = 226;
    }
    if($elesplit[0] eq 'Ac') {
        $wt = 227;
    }
    if($elesplit[0] eq 'Pa') {
        $wt = 231.03588;
    }
    if($elesplit[0] eq 'Th') {
        $wt = 232.03806;
    }
    if($elesplit[0] eq 'Np') {
        $wt = 237;
    }
    if($elesplit[0] eq 'U') {
        $wt = 238.02891;
    }
    if($elesplit[0] eq 'Am') {
        $wt = 243;
    }
    if($elesplit[0] eq 'Pu') {
        $wt = 244;
    }
    if($elesplit[0] eq 'Cm') {
        $wt = 247;
    }
    if($elesplit[0] eq 'Bk') {
        $wt = 247;
    }
    if($elesplit[0] eq 'Cf') {
        $wt = 251;
    }
    if($elesplit[0] eq 'Es') {
        $wt = 252;
    }
    if($elesplit[0] eq 'Fm') {
        $wt = 257;
    }
    if($elesplit[0] eq 'Md') {
        $wt = 258;
    }
    if($elesplit[0] eq 'No') {
        $wt = 259;
    }
    if($elesplit[0] eq 'Lr') {
        $wt = 262;
    }
    if($elesplit[0] eq 'Rf') {
        $wt = 261;
    }
    if($elesplit[0] eq 'Db') {
        $wt = 262;
    }
    if($elesplit[0] eq 'Sg') {
        $wt = 266;
    }
    if($elesplit[0] eq 'Bh') {
        $wt = 264;
    }
    if($elesplit[0] eq 'Hs') {
        $wt = 277;
    }
    if($elesplit[0] eq 'Mt') {
        $wt = 268;
    }
    if($elesplit[0] eq 'Ds') {
        $wt = 271;
    }
    if($elesplit[0] eq 'Rg') {
        $wt = 272;
    }
    if($elesplit[0] eq 'Uub') {
        $wt = 285;
    }
    if($elesplit[0] eq 'Uut') {
        $wt = 284;
    }
    if($elesplit[0] eq 'Uuq') {
        $wt = 289;
    }
    if($elesplit[0] eq 'Uup') {
        $wt = 288;
    }
    if($elesplit[0] eq 'Uuh') {
        $wt = 292;
    }
    if($elesplit[0] eq 'Uuo') {
        $wt = 294;
    }
    
    #perform element mass calcualtion
    $ewt = $wt * $elesplit[1];
    
    #add to molecular weight
    $molwt = $molwt + $ewt;
    
    if($num == $elenum) {
        die "Molecular weight = $molwt\n";
    }
    
    $num = $num+1;
}

is there a nicer way to do this?
 
Basically you simply need to use a hash as a lookup table. There are many different ways to initialize that hash, but I would suggest you create a list that is parsed.

Also, the logic that you are currently using to calculate is flawed in multiple ways.

Here is your code so modified and corrected:

Code:
[gray]#!/usr/bin/perl -w[/gray]
[gray][i]#perl2exe_include Math::BigInt[/i][/gray]
[gray][i]#perl2exe_include Math::BigInt::Calc[/i][/gray]

[gray][i]#molwt.pl : Calculates molecular weights[/i][/gray]
[gray][i]#Written by Luke Aaron[/i][/gray]
[gray][i]#Version B 30/01/08[/i][/gray]

[url=http://perldoc.perl.org/functions/use.html][black][b]use[/b][/black][/url] [green]bignum[/green][red];[/red]

[black][b]use[/b][/black] [green]strict[/green][red];[/red]
[black][b]use[/b][/black] [green]warnings[/green][red];[/red]

[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]%atomic_mass[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red][url=http://perldoc.perl.org/functions/chomp.html][black][b]chomp[/b][/black][/url][red];[/red] [red]/[/red][purple]^([purple][b]\w[/b][/purple]+)[purple][b]\s[/b][/purple]+(.*)[/purple][red]/[/red][red]}[/red] <DATA>[red];[/red]

[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]"[/red][purple][purple][b]\n[/b][/purple]Format example: Water written H-2O-1[purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]
[black][b]print[/b][/black]  [red]"[/red][purple]Enter Compound: [/purple][red]"[/red][red];[/red]
[black][b]my[/b][/black] [blue]$compound[/blue] = <STDIN>[red];[/red]
[black][b]chomp[/b][/black][red]([/red][blue]$compound[/blue][red])[/red][red];[/red]

[black][b]my[/b][/black] [blue]$molwt[/blue] = [fuchsia]0[/fuchsia][red];[/red]

[olive][b]while[/b][/olive] [red]([/red][blue]$compound[/blue] =~ [red]m{[/red][purple][purple][b]\G[/b][/purple] ([purple][b]\w[/b][/purple]+) - ([purple][b]\d[/b][/purple]+)[/purple][red]}[/red][red]gcx[/red][red])[/red] [red]{[/red]
	[black][b]my[/b][/black] [red]([/red][blue]$element[/blue], [blue]$count[/blue][red])[/red] = [red]([/red][blue]$1[/blue], [blue]$2[/blue][red])[/red][red];[/red]

	[gray][i]# Fix casing[/i][/gray]
	[blue]$element[/blue] = [url=http://perldoc.perl.org/functions/ucfirst.html][black][b]ucfirst[/b][/black][/url] [url=http://perldoc.perl.org/functions/lc.html][black][b]lc[/b][/black][/url] [blue]$element[/blue][red];[/red]

	[olive][b]if[/b][/olive] [red]([/red]! [url=http://perldoc.perl.org/functions/exists.html][black][b]exists[/b][/black][/url] [blue]$atomic_mass[/blue][red]{[/red][blue]$element[/blue][red]}[/red][red])[/red] [red]{[/red]
		[url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Element does not exist: '[blue]$element[/blue]'[/purple][red]"[/red][red];[/red]
	[red]}[/red]

	[blue]$molwt[/blue] += [blue]$atomic_mass[/blue][red]{[/red][blue]$element[/blue][red]}[/red] [blue]*[/blue] [blue]$count[/blue][red];[/red]
[red]}[/red]

[gray][i]# Did we make it through the entire string?[/i][/gray]
[olive][b]if[/b][/olive] [red]([/red][url=http://perldoc.perl.org/functions/pos.html][black][b]pos[/b][/black][/url] [blue]$compound[/blue] < [url=http://perldoc.perl.org/functions/length.html][black][b]length[/b][/black][/url] [blue]$compound[/blue][red])[/red] [red]{[/red]
	[black][b]my[/b][/black] [blue]$pos[/blue] = [black][b]pos[/b][/black] [blue]$compound[/blue][red];[/red]
	[blue]$compound[/blue] =~ [red]m{[/red][purple][purple][b]\G[/b][/purple] ([^[purple][b]\n[/b][/purple]]+)[/purple][red]}[/red][red]gcx[/red][red];[/red]
	[black][b]my[/b][/black] [blue]$context[/blue] = [blue]$1[/blue][red];[/red]
	[black][b]die[/b][/black] [red]"[/red][purple]Invalid input at position [blue]$pos[/blue]: [blue]$context[/blue][/purple][red]"[/red][red];[/red]
[red]}[/red]

[black][b]print[/b][/black] [red]"[/red][purple]Molecular weight = [blue]$molwt[/blue][purple][b]\n[/b][/purple][/purple][red]"[/red][red];[/red]


[teal]__DATA__[/teal]
[teal]H 1.00794[/teal]
[teal]He 4.002602[/teal]
[teal]Li 6.941[/teal]
[teal]Be 9.012182[/teal]
[teal]B 10.811[/teal]
[teal]C 12.0107[/teal]
[teal]N 14.0067[/teal]
[teal]O 15.9994[/teal]
[teal]F 18.9984032[/teal]
[teal]Ne 20.1797[/teal]
[teal]Na 22.98976928[/teal]
[teal]Mg 24.3050[/teal]
[teal]Al 26.9815386[/teal]
[teal]Si 28.0855[/teal]
[teal]P 30.973762[/teal]
[teal]S 32.065[/teal]
[teal]Cl 35.453[/teal]
[teal]K 39.0983[/teal]
[teal]Ar 39.948[/teal]
[teal]Ca 40.078[/teal]
[teal]Sc 44.955912[/teal]
[teal]Ti 47.867[/teal]
[teal]V 50.9415[/teal]
[teal]Cr 51.9961[/teal]
[teal]Mn 54.938045[/teal]
[teal]Fe 55.845[/teal]
[teal]Ni 58.6934[/teal]
[teal]Co 58.933195[/teal]
[teal]Cu 63.546[/teal]
[teal]Zn 65.409[/teal]
[teal]Ga 69.723[/teal]
[teal]Ge 72.64[/teal]
[teal]As 74.92160[/teal]
[teal]Se 78.96[/teal]
[teal]Br 79.904[/teal]
[teal]Kr 83.798[/teal]
[teal]Rb 85.4678[/teal]
[teal]Sr 97.62[/teal]
[teal]Y 88.90585[/teal]
[teal]Zr 91.224[/teal]
[teal]Nb 92.906[/teal]
[teal]Mo 95.94[/teal]
[teal]Tc 98[/teal]
[teal]Ru 101.07[/teal]
[teal]Rh 102.90550[/teal]
[teal]Pd 106.42[/teal]
[teal]Ag 107.8682[/teal]
[teal]Cd 112.411[/teal]
[teal]In 114.818[/teal]
[teal]Sn 118.710[/teal]
[teal]Sb 121.760[/teal]
[teal]Te 127.60[/teal]
[teal]I 126.90447[/teal]
[teal]Xe 131.293[/teal]
[teal]Cs 132.9054519[/teal]
[teal]Ba 137.327[/teal]
[teal]La 138.90547[/teal]
[teal]Ce 140.116[/teal]
[teal]Pr 140.90765[/teal]
[teal]Nd 144.242[/teal]
[teal]Pm 145[/teal]
[teal]Sm 150.36[/teal]
[teal]Eu 151.964[/teal]
[teal]Gd 157.25[/teal]
[teal]Tb 158.92535[/teal]
[teal]Dy 162.500[/teal]
[teal]Ho 164.930[/teal]
[teal]Er 167.259[/teal]
[teal]Tm 168.93421[/teal]
[teal]Yb 173.04[/teal]
[teal]Lu 174.967[/teal]
[teal]Hf 178.49[/teal]
[teal]Ta 180.94788[/teal]
[teal]W 183.84[/teal]
[teal]Re 186.207[/teal]
[teal]Os 190.23[/teal]
[teal]Ir 192.217[/teal]
[teal]Pt 195.084[/teal]
[teal]Au 196.966569[/teal]
[teal]Hg 200.59[/teal]
[teal]Tl 204.3833[/teal]
[teal]Pb 207.2[/teal]
[teal]Bi 208.98040[/teal]
[teal]Po 210[/teal]
[teal]At 210[/teal]
[teal]Rn 220[/teal]
[teal]Fr 223[/teal]
[teal]Ra 226[/teal]
[teal]Ac 227[/teal]
[teal]Pa 231.03588[/teal]
[teal]Th 232.03806[/teal]
[teal]Np 237[/teal]
[teal]U 238.02891[/teal]
[teal]Am 243[/teal]
[teal]Pu 244[/teal]
[teal]Cm 247[/teal]
[teal]Bk 247[/teal]
[teal]Cf 251[/teal]
[teal]Es 252[/teal]
[teal]Fm 257[/teal]
[teal]Md 258[/teal]
[teal]No 259[/teal]
[teal]Lr 262[/teal]
[teal]Rf 261[/teal]
[teal]Db 262[/teal]
[teal]Sg 266[/teal]
[teal]Bh 264[/teal]
[teal]Hs 277[/teal]
[teal]Mt 268[/teal]
[teal]Ds 271[/teal]
[teal]Rg 272[/teal]
[teal]Uub 285[/teal]
[teal]Uut 284[/teal]
[teal]Uuq 289[/teal]
[teal]Uup 288[/teal]
[teal]Uuh 292[/teal]
[teal]Uuo 294[/teal]
[tt]------------------------------------------------------------
Pragmas (perl 5.10.0) used :
[ul]
[li]bignum - Transparent BigNumber support for Perl[/li]
[li]strict - Perl pragma to restrict unsafe constructs[/li]
[li]warnings - Perl pragma to control optional warnings[/li]
[/ul]
[/tt]

- Miller
 
Use a hash to provide a lookup for the atomic weights
Code:
use strict;
use warnings;

my %periodic;

while (<DATA>) {
   chomp;
   my ($element, $weight) = split;
   $periodic{$element} = $weight;
}

my $ele = "He";

print "The weight of $ele is $periodic{$ele}\n";

__DATA__
H  1.00794
He 4.002602
Li 6.941
Uuo 294
You'll appreciate that I haven't typed in all the elements in the list...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
But I see that MillerH has. This is getting really tiresome...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
Sorry about that Steve. I just copy/pasted it in and didn't really think about how much space it would take up.

Thanks for both of your inputs :)
 
As steve demonstrated, my initialization of the lookup hash could be simplified a little:

Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]%atomic_mass[/blue] = [url=http://perldoc.perl.org/functions/map.html][black][b]map[/b][/black][/url] [red]{[/red][url=http://perldoc.perl.org/functions/chomp.html][black][b]chomp[/b][/black][/url][red];[/red] [url=http://perldoc.perl.org/functions/split.html][black][b]split[/b][/black][/url][red]}[/red] <DATA>[red];[/red]

- Miller
 
MonsterAar

Not your fault. I'm having a bit of an issue lately where I post a solution here only to discover that someone (usually MillerH or KevinADC) has beaten me to it! [smile]

Anyway, with my design head on, it makes sense to move the data about elements and weights outside the program, perhaps even to an external file. It reduces clutter, and lends itself to the addition of other attributes for the elements to support future enhancements. And of course, in the event that Unobtainium is discovered anytime soon it can be simply added to the table by a non-programmer...

Steve

[small]"Every program can be reduced by one instruction, and every program has at least one bug. Therefore, any program can be reduced to one instruction which doesn't work." (Object::perlDesignPatterns)[/small]
 
I did consider putting the data in an external file but decided not to because if somehow the file and the script got separated there'd be error messages spitting themselves everywhere. I thought it would be handy to have it all in one file. I'll just put some comments in about editing the lookup hash.

Thanks guys,
Luke
 
You just put one error catch at the top of your script for when you open the file,
open(FILE, "</path/to/file") or die "/path/to/file is missing, this script will not run with out that file present\n";

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[noevil]
Travis - Those who say it cannot be done are usually interrupted by someone else doing it; Give the wrong symptoms, get the wrong solutions;
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top