Chemical calculator: Difference between revisions

Content added Content deleted
m (syntax highlighting fixup automation)
m (Automated syntax highlighting fixup (second round - minor fixes))
Line 136: Line 136:


;Examples:
;Examples:
<syntaxhighlight lang=python>assert 1.008 == molar_mass('H') # hydrogen
<syntaxhighlight lang="python">assert 1.008 == molar_mass('H') # hydrogen
assert 2.016 == molar_mass('H2') # hydrogen gas
assert 2.016 == molar_mass('H2') # hydrogen gas
assert 18.015 == molar_mass('H2O') # water
assert 18.015 == molar_mass('H2O') # water
Line 152: Line 152:
:* &nbsp; Wikipedia article: &nbsp; [https://en.wikipedia.org/wiki/Molecular_mass Molecular mass]
:* &nbsp; Wikipedia article: &nbsp; [https://en.wikipedia.org/wiki/Molecular_mass Molecular mass]
<br><br>
<br><br>

=={{header|ALGOL W}}==
=={{header|ALGOL W}}==
Algol W has fixed length strings and no regular expressions, this parses the molecule with a simple recursive descent parser.<br>
Algol W has fixed length strings and no regular expressions, this parses the molecule with a simple recursive descent parser.<br>
Some error checking is included.
Some error checking is included.
<syntaxhighlight lang=algolw>begin
<syntaxhighlight lang="algolw">begin
% calculates the molar mass of the specified molecule %
% calculates the molar mass of the specified molecule %
real procedure molar_mass ( string(256) value molecule ) ; begin
real procedure molar_mass ( string(256) value molecule ) ; begin
Line 314: Line 313:
UueCl : 350.450
UueCl : 350.450
</pre>
</pre>

=={{header|AutoHotkey}}==
=={{header|AutoHotkey}}==
<syntaxhighlight lang=AutoHotkey>test := ["H", "H2", "H2O", "H2O2", "(HO)2", "Na2SO4", "C6H12", "COOH(C(CH3)2)3CH3", "C6H4O2(OH)4", "C27H46O"
<syntaxhighlight lang="autohotkey">test := ["H", "H2", "H2O", "H2O2", "(HO)2", "Na2SO4", "C6H12", "COOH(C(CH3)2)3CH3", "C6H4O2(OH)4", "C27H46O"
, "Uue", "C6H4O2(O)H)4", "X2O"]
, "Uue", "C6H4O2(O)H)4", "X2O"]
for i, str in test
for i, str in test
Line 370: Line 368:
C6H4O2(O)H)4 > Invalid Group
C6H4O2(O)H)4 > Invalid Group
X2O > Invalid atom name</pre>
X2O > Invalid atom name</pre>

=={{header|C}}==
=={{header|C}}==
<syntaxhighlight lang=c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>
Line 648: Line 645:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|C sharp|C#}}==
=={{header|C sharp|C#}}==
{{trans|D}}
{{trans|D}}
<syntaxhighlight lang=csharp>using System;
<syntaxhighlight lang="csharp">using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using System.Linq;
Line 854: Line 850:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|C++}}==
=={{header|C++}}==
{{trans|C#}}
{{trans|C#}}
<syntaxhighlight lang=cpp>#include <iomanip>
<syntaxhighlight lang="cpp">#include <iomanip>
#include <iostream>
#include <iostream>
#include <map>
#include <map>
Line 1,067: Line 1,062:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|CoffeeScript}}==
=={{header|CoffeeScript}}==
===No Regular Expression===
===No Regular Expression===
<syntaxhighlight lang=coffeescript>ATOMIC_MASS = {H:1.008,C:12.011,O:15.999,Na:22.98976928,S:32.06,Uue:315}
<syntaxhighlight lang="coffeescript">ATOMIC_MASS = {H:1.008,C:12.011,O:15.999,Na:22.98976928,S:32.06,Uue:315}


molar_mass = (s) ->
molar_mass = (s) ->
Line 1,105: Line 1,099:
===Regular Expression===
===Regular Expression===
{{trans|Julia}}
{{trans|Julia}}
<syntaxhighlight lang=coffeescript>ATOMIC_MASS = {H:1.008,C:12.011,O:15.999,Na:22.98976928,S:32.06,Uue:315}
<syntaxhighlight lang="coffeescript">ATOMIC_MASS = {H:1.008,C:12.011,O:15.999,Na:22.98976928,S:32.06,Uue:315}


mul = (match, p1, offset, string) -> '*' + p1
mul = (match, p1, offset, string) -> '*' + p1
Line 1,128: Line 1,122:
assert 386.664, molar_mass('C27H46O') # Cholesterol
assert 386.664, molar_mass('C27H46O') # Cholesterol
assert 315, molar_mass('Uue')</syntaxhighlight>
assert 315, molar_mass('Uue')</syntaxhighlight>

=={{header|D}}==
=={{header|D}}==
{{trans|Go}}
{{trans|Go}}
<syntaxhighlight lang=d>import std.array;
<syntaxhighlight lang="d">import std.array;
import std.conv;
import std.conv;
import std.format;
import std.format;
Line 1,325: Line 1,318:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Delphi}}==
=={{header|Delphi}}==
{{trans|Go}}
{{trans|Go}}
<syntaxhighlight lang=Delphi>
<syntaxhighlight lang="delphi">
program ChemicalCalculator;
program ChemicalCalculator;


Line 1,480: Line 1,472:
</syntaxhighlight>
</syntaxhighlight>
Include file with Atomic Mass Constants ('''AtomicMass.inc''').
Include file with Atomic Mass Constants ('''AtomicMass.inc''').
<syntaxhighlight lang=Delphi>
<syntaxhighlight lang="delphi">
const
const
ATOMIC_MASS_SIZE = 101;
ATOMIC_MASS_SIZE = 101;
Line 1,507: Line 1,499:
257, 315, 299);
257, 315, 299);
</syntaxhighlight>
</syntaxhighlight>



=={{header|Factor}}==
=={{header|Factor}}==
{{works with|Factor|0.98}}
{{works with|Factor|0.98}}
<syntaxhighlight lang=factor>USING: assocs compiler.units definitions grouping infix.parser
<syntaxhighlight lang="factor">USING: assocs compiler.units definitions grouping infix.parser
infix.private kernel math.functions math.parser multiline
infix.private kernel math.functions math.parser multiline
peg.ebnf qw sequences splitting strings words words.constant ;
peg.ebnf qw sequences splitting strings words words.constant ;
Line 1,609: Line 1,598:
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code.
The option to show Fōrmulæ programs and their results is showing images. Unfortunately images cannot be uploaded in Rosetta Code.
-->
-->

=={{header|Go}}==
=={{header|Go}}==
This doesn't use regular expressions, RPN or eval (which Go doesn't have). It's just a simple molar mass evaluator written from scratch.
This doesn't use regular expressions, RPN or eval (which Go doesn't have). It's just a simple molar mass evaluator written from scratch.
<syntaxhighlight lang=go>package main
<syntaxhighlight lang="go">package main


import (
import (
Line 1,806: Line 1,794:
Uue -> 315.000
Uue -> 315.000
</pre>
</pre>

=={{header|Groovy}}==
=={{header|Groovy}}==
{{trans|Java}}
{{trans|Java}}
<syntaxhighlight lang=groovy>import java.util.regex.Pattern
<syntaxhighlight lang="groovy">import java.util.regex.Pattern


class ChemicalCalculator {
class ChemicalCalculator {
Line 2,000: Line 1,987:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Haskell}}==
=={{header|Haskell}}==
Create a set of parsers for molecular formulae and their subparts. The parsers maintain a running total of the mass parsed so far. Use a '''Reader''' monad to store a map from atom names to their masses. The contents of the map are read from the file '''chemcalc_masses.in''', not shown here.
Create a set of parsers for molecular formulae and their subparts. The parsers maintain a running total of the mass parsed so far. Use a '''Reader''' monad to store a map from atom names to their masses. The contents of the map are read from the file '''chemcalc_masses.in''', not shown here.
<syntaxhighlight lang=haskell>import Control.Monad (forM_)
<syntaxhighlight lang="haskell">import Control.Monad (forM_)
import Control.Monad.Reader (Reader, ask, runReader)
import Control.Monad.Reader (Reader, ask, runReader)
import Data.Bifunctor (first)
import Data.Bifunctor (first)
Line 2,087: Line 2,073:
invalid atom name starting here
invalid atom name starting here
</pre>
</pre>

=={{header|Java}}==
=={{header|Java}}==
{{trans|Kotlin}}
{{trans|Kotlin}}
<syntaxhighlight lang=java>import java.util.HashMap;
<syntaxhighlight lang="java">import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.Map;
import java.util.Map;
Line 2,284: Line 2,269:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|JavaScript}}==
=={{header|JavaScript}}==
<syntaxhighlight lang=javascript>
<syntaxhighlight lang="javascript">
const MASSES = {
const MASSES = {
C: 12.011,
C: 12.011,
Line 2,334: Line 2,318:
Uue: 315
Uue: 315
</pre>
</pre>

=={{header|jq}}==
=={{header|jq}}==
{{works with|jq}}
{{works with|jq}}
Line 2,362: Line 2,345:


'''The PEG grammar'''
'''The PEG grammar'''
<syntaxhighlight lang=jq>def Element:
<syntaxhighlight lang="jq">def Element:
parse("(?<e>^[A-Z][a-z]*)"); # greedy
parse("(?<e>^[A-Z][a-z]*)"); # greedy


Line 2,384: Line 2,367:


'''The task expressed in terms of assertions'''
'''The task expressed in terms of assertions'''
<syntaxhighlight lang=text># A "debug" statement has been retained so that the parsed chemical formula can be seen.
<syntaxhighlight lang="text"># A "debug" statement has been retained so that the parsed chemical formula can be seen.
def molar_mass(formula):
def molar_mass(formula):
{remainder: formula} | Formula | .result | debug | eval;
{remainder: formula} | Formula | .result | debug | eval;
Line 2,419: Line 2,402:
["DEBUG:",["Uue"]]
["DEBUG:",["Uue"]]
</pre>
</pre>

=={{header|Julia}}==
=={{header|Julia}}==
Note that Julia's 64-bit floating point gets a slightly different result for one of the assertions, hence a small change in the last example. The function uses Julia's own language parser to evaluate the compound as an arithmetic expression.
Note that Julia's 64-bit floating point gets a slightly different result for one of the assertions, hence a small change in the last example. The function uses Julia's own language parser to evaluate the compound as an arithmetic expression.
<syntaxhighlight lang=julia>const H = 1.008
<syntaxhighlight lang="julia">const H = 1.008
const He = 4.002602
const He = 4.002602
const Li = 6.94
const Li = 6.94
Line 2,537: Line 2,519:
</syntaxhighlight>
</syntaxhighlight>
No assertion errors.
No assertion errors.

=={{header|Kotlin}}==
=={{header|Kotlin}}==
{{trans|D}}
{{trans|D}}
<syntaxhighlight lang=scala>var atomicMass = mutableMapOf(
<syntaxhighlight lang="scala">var atomicMass = mutableMapOf(
"H" to 1.008,
"H" to 1.008,
"He" to 4.002602,
"He" to 4.002602,
Line 2,727: Line 2,708:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Lua}}==
=={{header|Lua}}==
{{trans|C#}}
{{trans|C#}}
<syntaxhighlight lang=lua>atomicMass = {
<syntaxhighlight lang="lua">atomicMass = {
["H"] = 1.008,
["H"] = 1.008,
["He"] = 4.002602,
["He"] = 4.002602,
Line 2,920: Line 2,900:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Nim}}==
=={{header|Nim}}==
* Nim lacks runtime eval, that's the reason for so much code. (And me being a sloppy programmer)
* Nim lacks runtime eval, that's the reason for so much code. (And me being a sloppy programmer)
* Also, seqs can't contain mixed types.
* Also, seqs can't contain mixed types.


<syntaxhighlight lang=python>#? replace(sub = "\t", by = " ")
<syntaxhighlight lang="python">#? replace(sub = "\t", by = " ")


import tables, strutils, sequtils, math
import tables, strutils, sequtils, math
Line 3,037: Line 3,016:
assert 386.664 == molar_mass "C27H46O" # Cholesterol
assert 386.664 == molar_mass "C27H46O" # Cholesterol
assert 315 == molar_mass "Uue"</syntaxhighlight>
assert 315 == molar_mass "Uue"</syntaxhighlight>

=={{header|Perl}}==
=={{header|Perl}}==
===Grammar===
===Grammar===
<syntaxhighlight lang=perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
use List::Util;
use List::Util;
Line 3,063: Line 3,041:


===Regular Expression===
===Regular Expression===
<syntaxhighlight lang=perl>use strict;
<syntaxhighlight lang="perl">use strict;
use warnings;
use warnings;
my %atomic_weight = < H 1.008 C 12.011 O 15.999 Na 22.99 S 32.06 >;
my %atomic_weight = < H 1.008 C 12.011 O 15.999 Na 22.99 S 32.06 >;
Line 3,096: Line 3,074:
84.162 C6H12 C6H12
84.162 C6H12 C6H12
186.295 C11H22O2 COOH(C(CH3)2)3CH3</pre>
186.295 C11H22O2 COOH(C(CH3)2)3CH3</pre>

=={{header|Phix}}==
=={{header|Phix}}==
A simple hand-written single-pass formula parser and evaluator in one.<br>
A simple hand-written single-pass formula parser and evaluator in one.<br>
Line 3,102: Line 3,079:
Also note that initially it all worked absolutely fine with the default precision (ie "%g" instead of "%.12g"),
Also note that initially it all worked absolutely fine with the default precision (ie "%g" instead of "%.12g"),
and that the higher precision expected value for Na2SO4 also works just fine at both printing precisions.
and that the higher precision expected value for Na2SO4 also works just fine at both printing precisions.
<!--<syntaxhighlight lang=Phix>(phixonline)-->
<!--<syntaxhighlight lang="phix">(phixonline)-->
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">elements</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- (eg "H" -&gt; 1.008)</span>
<span style="color: #008080;">constant</span> <span style="color: #000000;">elements</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">new_dict</span><span style="color: #0000FF;">()</span> <span style="color: #000080;font-style:italic;">-- (eg "H" -&gt; 1.008)</span>
Line 3,211: Line 3,188:
UueCl = 350.45
UueCl = 350.45
</pre>
</pre>

=={{header|Python}}==
=={{header|Python}}==
{{trans|Julia}}
{{trans|Julia}}
<syntaxhighlight lang=python>import re
<syntaxhighlight lang="python">import re


ATOMIC_MASS = {"H":1.008, "C":12.011, "O":15.999, "Na":22.98976928, "S":32.06, "Uue":315}
ATOMIC_MASS = {"H":1.008, "C":12.011, "O":15.999, "Na":22.98976928, "S":32.06, "Uue":315}
Line 3,242: Line 3,218:
Atomic mass C27H46O 386.664
Atomic mass C27H46O 386.664
Atomic mass Uue 315.000</pre>
Atomic mass Uue 315.000</pre>

=={{header|Racket}}==
=={{header|Racket}}==


<syntaxhighlight lang=racket>#lang racket
<syntaxhighlight lang="racket">#lang racket


(define table '([H 1.008]
(define table '([H 1.008]
Line 3,301: Line 3,276:
Uue: 315
Uue: 315
</pre>
</pre>

=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)
<syntaxhighlight lang=raku line>my %ATOMIC_MASS =
<syntaxhighlight lang="raku" line>my %ATOMIC_MASS =
H => 1.008 , Fe => 55.845 , Te => 127.60 , Ir => 192.217 ,
H => 1.008 , Fe => 55.845 , Te => 127.60 , Ir => 192.217 ,
He => 4.002602 , Co => 58.933194 , I => 126.90447 , Pt => 195.084 ,
He => 4.002602 , Co => 58.933194 , I => 126.90447 , Pt => 195.084 ,
Line 3,361: Line 3,335:
84.162 C6H12
84.162 C6H12
186.295 COOH(C(CH3)2)3CH3</pre>
186.295 COOH(C(CH3)2)3CH3</pre>

=={{header|REXX}}==
=={{header|REXX}}==
This REXX version has some basic error checking to catch malformed chemical formulas.
This REXX version has some basic error checking to catch malformed chemical formulas.
Line 3,375: Line 3,348:
roentgenium (Rg), copernicium (Cn), nihoniym (Nh), flerovium (Fl), moscovium (Mc),
roentgenium (Rg), copernicium (Cn), nihoniym (Nh), flerovium (Fl), moscovium (Mc),
livermorium (Lv), tennessine (Ts), oganesson (Og)
livermorium (Lv), tennessine (Ts), oganesson (Og)
<syntaxhighlight lang=rexx>/*REXX program calculates the molar mass from a specified chemical formula. */
<syntaxhighlight lang="rexx">/*REXX program calculates the molar mass from a specified chemical formula. */
numeric digits 30 /*ensure enough decimal digits for mass*/
numeric digits 30 /*ensure enough decimal digits for mass*/
/*─────────── [↓] table of known elements (+2 more) with their atomic mass ────────────*/
/*─────────── [↓] table of known elements (+2 more) with their atomic mass ────────────*/
Line 3,473: Line 3,446:
Mg3Si4O10(OH)2 {talc} 379.26568
Mg3Si4O10(OH)2 {talc} 379.26568
</pre>
</pre>

=={{header|Ruby}}==
=={{header|Ruby}}==
{{trans|D}}
{{trans|D}}
<syntaxhighlight lang=ruby>$atomicMass = {
<syntaxhighlight lang="ruby">$atomicMass = {
"H" => 1.008,
"H" => 1.008,
"He" => 4.002602,
"He" => 4.002602,
Line 3,667: Line 3,639:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Swift}}==
=={{header|Swift}}==


<syntaxhighlight lang=swift>import Foundation
<syntaxhighlight lang="swift">import Foundation


struct Chem {
struct Chem {
Line 3,954: Line 3,925:
C27H46O => 386.664
C27H46O => 386.664
Uue => 315.000</pre>
Uue => 315.000</pre>

=={{header|VBA}}==
=={{header|VBA}}==
<syntaxhighlight lang=vba>Option Explicit
<syntaxhighlight lang="vba">Option Explicit


Enum ParsingStateCode
Enum ParsingStateCode
Line 4,143: Line 4,113:
C27H46O 386,664
C27H46O 386,664
Uue 315</pre>
Uue 315</pre>

=={{header|Visual Basic .NET}}==
=={{header|Visual Basic .NET}}==
{{trans|C#}}
{{trans|C#}}
<syntaxhighlight lang=vbnet>Module Module1
<syntaxhighlight lang="vbnet">Module Module1


Dim atomicMass As New Dictionary(Of String, Double) From {
Dim atomicMass As New Dictionary(Of String, Double) From {
Line 4,343: Line 4,312:
C27H46O -> 386.664
C27H46O -> 386.664
Uue -> 315.000</pre>
Uue -> 315.000</pre>

=={{header|Wren}}==
=={{header|Wren}}==
{{trans|Go}}
{{trans|Go}}
{{libheader|Wren-fmt}}
{{libheader|Wren-fmt}}
{{libheader|Wren-str}}
{{libheader|Wren-str}}
<syntaxhighlight lang=ecmascript>import "/fmt" for Fmt
<syntaxhighlight lang="ecmascript">import "/fmt" for Fmt
import "/str" for Char, Str
import "/str" for Char, Str


Line 4,539: Line 4,507:
Uue -> 315.000
Uue -> 315.000
</pre>
</pre>

=={{header|zkl}}==
=={{header|zkl}}==
Really bad error checking
Really bad error checking
<syntaxhighlight lang=zkl>fcn molarMass(str,mass=0.0){
<syntaxhighlight lang="zkl">fcn molarMass(str,mass=0.0){
while(span:=str.span("(",")",False)){ // get inner most () group
while(span:=str.span("(",")",False)){ // get inner most () group
group:=str[span.xplode()]; // (CH3)
group:=str[span.xplode()]; // (CH3)
Line 4,562: Line 4,529:
ms.reduce('+);
ms.reduce('+);
}</syntaxhighlight>
}</syntaxhighlight>
<syntaxhighlight lang=zkl>var [const] atomicMass = Dictionary(
<syntaxhighlight lang="zkl">var [const] atomicMass = Dictionary(
"Ac",227.000000, "Ag",107.868200, "Al", 26.981538, "Am",243.000000, "Ar", 39.948000,
"Ac",227.000000, "Ag",107.868200, "Al", 26.981538, "Am",243.000000, "Ar", 39.948000,
"As", 74.921595, "At",210.000000, "Au",196.966569, "B" , 10.810000, "Ba",137.327000,
"As", 74.921595, "At",210.000000, "Au",196.966569, "B" , 10.810000, "Ba",137.327000,
Line 4,591: Line 4,558:
: RegExp(_);
: RegExp(_);
}();</syntaxhighlight>
}();</syntaxhighlight>
<syntaxhighlight lang=zkl>foreach cstr in (T("H","H2","H2O","Na2SO4","C6H12","COOH(C(CH3)2)3CH3"))
<syntaxhighlight lang="zkl">foreach cstr in (T("H","H2","H2O","Na2SO4","C6H12","COOH(C(CH3)2)3CH3"))
{ println(cstr," --> ",molarMass(cstr)) }</syntaxhighlight>
{ println(cstr," --> ",molarMass(cstr)) }</syntaxhighlight>
{{out}}
{{out}}