找到给定化合物的先生!


12

挑战

给定化学式,输出化合物的M r

方程

化合物中的每个元素后跟一个数字,表示化合物中所述原子的数目。如果没有数字,则化合物中只有一个原子。

一些例子是:

  • 乙醇(C 2 H 6 O)将C2H6O存在两个碳原子,6个氢原子和1个氧原子
  • 氢氧化镁(MgO 2 H 2)将MgO2H2存在一个镁原子,两个氧原子和两个氢原子。

请注意,您将不必处理方括号,并且每个元素在公式中仅包含一次。

虽然大多数人可能会坚持自己最满意的顺序,但没有严格的订购系统。例如,水可以是H2OOH2

中号[R

注意:此处,假设分子式质量与分子质量相同

化合物的M r,即分子量,是分子中原子的原子量的总和。

您必须支持的唯一元素及其原子量(小数点后一位)(氢到钙,不包括稀有气体)如下。他们也可以在这里找到

H  - 1.0      Li - 6.9      Be - 9.0
B  - 10.8     C  - 12.0     N  - 14.0
O  - 16.0     F  - 19.0     Na - 23.0
Mg - 24.3     Al - 27.0     Si - 28.1
P  - 31.0     S  - 32.1     Cl - 35.5
K  - 39.1     Ca - 40.1

您应该始终将输出保留到小数点后一位。

例如,乙醇(C2H6O)的M r为,46.0因为它是其中元素的原子量之和:

12.0 + 12.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 1.0 + 16.0
(2*C + 6*H + 1*O)

输入值

具有上述格式的单个字符串。您可以保证等式中包含的元素将是实际的元素符号。

给定的化合物不能保证确实存在。

输出量

化合物的总M r,小数点后一位。

规则

禁止访问元素或化学数据的内建函数(对不起,Mathematica)

例子

Input > Output
CaCO3 > 100.1
H2SO4 > 98.1
SF6 > 146.1
C100H202O53 > 2250.0

获奖

以字节为单位的最短代码获胜。

该职位是在caird coinheringaahing的允许下通过的。(现在删除帖子)


难道我们必须处理量词,如:2H2O
Xcoder先生17年

6
出于好奇,这是Mathematica解决方案(53字节):NumberForm[#&@@#~ChemicalData~"MolecularMass",{9,1}]&
JungHwan Min

Answers:


6

果冻,63 个字节

ḟØDOP%⁽¡ṛị“ÇṚÆ’BH+“Ḳ"ɦṀ⁷6<s¡_-¦y⁼Ḟ¡¡FPɓ‘¤÷5
fØDVȯ1×Ç
Œs>œṗ⁸ḊÇ€S

接受字符列表并返回数字的单子链接。

在线尝试!

怎么样?

ḟØDOP%⁽¡ṛị“ÇṚÆ’BH+“Ḳ"ɦṀ⁷6<s¡_-¦y⁼Ḟ¡¡FPɓ‘¤÷5 - Link 1, Atomic weight: list of characters
                                            -                              e.g. "Cl23"
 ØD                                         - digit yield = "0123456789"
ḟ                                           - filter discard                      "Cl"
   O                                        - cast to ordinals                [67,108]
    P                                       - product                            7236
      ⁽¡ṛ                                   - base 250 literal = 1223
     %                                      - modulo                             1121
                                        ¤   - nilad followed by link(s) as a nilad:
          “ÇṚÆ’                             -   base 250 literal  = 983264
               B                            -   convert to binary = [    1,    1,     1,     1,   0,  0,  0,   0, 0,  0,  0, 0,     1,     1,     1, 0, 0,  0,  0,   0]
                H                           -   halve             = [  0.5,  0.5,   0.5,   0.5,   0,  0,  0,   0, 0,  0,  0, 0,   0.5,   0.5,   0.5, 0, 0,  0,  0,   0]
                  “Ḳ"ɦṀ⁷6<s¡_-¦y⁼Ḟ¡¡FPɓ‘    -   code-page indexes = [177  , 34  , 160  , 200  , 135, 54, 60, 115, 0, 95, 45, 5, 121  , 140  , 195  , 0, 0, 70, 80, 155]
                 +                          -   addition          = [177.5, 34.5, 160.5, 200.5, 135, 54, 60, 115, 0, 95, 45, 5, 121.5, 140.5, 195.5, 0, 0, 70, 80, 155]
         ị                                  - index into (1-indexed and modular)
                                            -    ...20 items so e.g. 1121%20=1 so 177.5
                                         ÷5 - divide by 5                          35.5

fØDVȯ1×Ç - Link 2: Total weight of multiple of atoms: list of characters   e.g. "Cl23"
 ØD      - digit yield = "0123456789"
f        - filter keep                                                            "23"
   V     - evaluate as Jelly code                                                  23
    ȯ1   - logical or with one (no digits yields an empty string which evaluates to zero)
       Ç - call last link (1) as a monad (get the atomic weight)                   35.5
      ×  - multiply                                                               816.5

Œs>œṗ⁸ḊÇ€S - Main link: list of characters                             e.g. "C24HCl23"
Œs         - swap case                                                      "c24hcL23"
  >        - greater than? (vectorises)                                      10011000
     ⁸     - chain's left argument                                          "C24HCl23"
   œṗ      - partition at truthy indexes                          ["","C24","H","Cl23"]
      Ḋ    - dequeue                                                 ["C24","H","Cl23"]
       Ç€  - call last link (2) as a monad for €ach                  [  288,  1,  816.5]
         S - sum                                                                 1105.5

这是我见过的最长的Jelly答案之一,但它仍不到当前程序长度的一半,仅次于第二名,很好!
狮ry

6

Python 3中 189个182  168字节

使用Justin Mariner的JavaScript(ES6)answer中的哈希值来生成-14个字节。

import re
lambda s:sum([[9,35.5,39.1,24.3,28.1,14,16,31,40.1,23,32.1,10.8,12,27,6.9,19,0,1][int(a,29)%633%35%18]*int(n or 1)for a,n in re.findall("(\D[a-z]?)(\d*)",s)])

在线尝试!


下面是182字节的版本,下面我将对此进行解释-上面只是更改权重的顺序,用于int从base转换元素名称29,并使用不同的除数将整数范围向下压缩-请参见Justin水手的回答

import re
lambda s:sum([[16,31,40.1,32.1,0,24.3,12,39.1,28.1,19,0,9,10.8,23,27,35.5,6.9,14,1][ord(a[0])*ord(a[-1])%1135%98%19]*int(n or 1)for a,n in re.findall("(\D[a-z]?)(\d*)",s)])

一个未命名的函数,它接受字符串s,并返回一个数字。

在线尝试!

怎么样?

使用正则表达式使用以下命令将输入​​,s分为元素及其计数:
re.findall("(\D[a-z]?)(\d*)",s)
\D精确匹配一个非数字并[a-z]?匹配0或1个小写字母,以及匹配元素。\d*匹配0个或多个数字。括号将它们分成两组,因此findall("...",s)返回字符串元组列表[(element, number),...]

该数字很容易提取,唯一要处理的是空字符串表示1,这是通过逻辑实现的,or因为Python字符串为falsey int(n or 1)

元素字符串通过取其第一个和最后一个字符的序数的乘积来赋予唯一编号(通常这些相同,例如S或C,但是我们需要区分Cl,C,Ca和Na,因此我们不能仅使用一个字符)。

然后,对这些数字进行哈希处理以覆盖[0,18]的更小范围,该范围是通过搜索导致的模空间而找到的%1135%98%19。例如,"Cl"有序号67108乘以得到7736,模1135426,模9834,模1915;该数值用于索引到整数列表- 15日在列表(0-索引)值:
[16,31,40.1,32.1,0,24.3,12,39.1,28.1,19,0,9,10.8,23,27,35.5,6.9,14,1]
35.5,原子重量的Cl,然后通过这样的元件的数量相乘(如上述实测值)。

然后使用将这些产品加在一起sum(...)


您真是个天才……让我失望了350多个字节
Xcoder先生,2017年

4

PHP,235字节

preg_match_all("#([A-Z][a-z]?)(\d*)#",$argn,$m);foreach($m[1]as$v)$s+=array_combine([H,Li,Be,B,C,N,O,F,Na,Mg,Al,Si,P,S,Cl,K,Ca],[1,6.9,9,10.8,12,14,16,19,23,24.3,27,28.1,31,32.1,35.5,39.1,40.1])[$v]*($m[2][+$k++]?:1);printf("%.1f",$s);

在线尝试!

而不是array_combine([H,Li,Be,B,C,N,O,F,Na,Mg,Al,Si,P,S,Cl,K,Ca],[1,6.9,9,10.8,12,14,16,19,23,24.3,27,28.1,31,32.1,35.5,39.1,40.1])您可以使用[H=>1,Li=>6.9,Be=>9,B=>10.8,C=>12,N=>14,O=>16,F=>19,Na=>23,Mg=>24.3,Al=>27,Si=>28.1,P=>31,S=>32.1,Cl=>35.5,K=>39.1,Ca=>40.1]相同的字节数


3

JavaScript(ES6),150字节

c=>c.replace(/(\D[a-z]?)(\d+)?/g,(_,e,n=1)=>s+=[9,35.5,39.1,24.3,28.1,14,16,31,40.1,23,32.1,10.8,12,27,6.9,19,0,1][parseInt(e,29)%633%35%18]*n,s=0)&&s

受到乔纳森·艾伦Jonathan Allan)的Python答案的启发,他在其中解释了给每个元素一个唯一的数字并将这些数字散列在较小范围内的情况。

通过将元素解释为以29为基数(0-9和AS),这些元素被制成唯一的数字。然后,我发现可以%633%35%18将值缩小到的范围,[0, 17]同时保持唯一性。

测试片段

f=
c=>c.replace(/(\D[a-z]?)(\d+)?/g,(_,e,n=1)=>s+=[9,35.5,39.1,24.3,28.1,14,16,31,40.1,23,32.1,10.8,12,27,6.9,19,0,1][parseInt(e,29)%633%35%18]*n,s=0)&&s
Input: <input oninput="O.value=f(this.value)"><br>
Result: <input id="O" disabled>


哦,我想您的方式也可以节省一些字节!
乔纳森·艾伦,

2

Clojure,198194字节

更新:更好的forreduce

#(apply +(for[[_ e n](re-seq #"([A-Z][a-z]?)([0-9]*)"%)](*(if(=""n)1(Integer. n))({"H"1"B"10.8"O"16"Mg"24.3"P"31"K"39.1"Li"6.9"C"12"F"19"Al"2"S"32.1"Ca"40.1"Be"9"N"14"Na"23"Si"28.1"Cl"35.5}e))))

原版的:

#(reduce(fn[r[_ e n]](+(*(if(=""n)1(Integer. n))({"H"1"B"10.8"O"16"Mg"24.3"P"31"K"39.1"Li"6.9"C"12"F"19"Al"2"S"32.1"Ca"40.1"Be"9"N"14"Na"23"Si"28.1"Cl"35.5}e))r))0(re-seq #"([A-Z][a-z]?)([0-9]*)"%))

我想知道是否有一种更紧凑的方式来编码查询表。


2

Python 3,253字节

def m(f,j=0):
 b=j+1
 while'`'<f[b:]<'{':b+=1
 c=b
 while'.'<f[c:]<':':c+=1
 return[6.9,9,23,40.1,24.3,27,28.1,35.5,31,32.1,39.1,1,10.8,12,14,16,19]['Li Be Na Ca Mg Al Si Cl P S K H B C N O F'.split().index(f[j:b])]*int(f[b:c]or 1)+(f[c:]>' 'and m(f,c))

在线尝试!


1

数学,390个 338个 329字节

由于实际上已经醒着并且实际上使用了我打算的缩短时间,因此节省了9个字节。

版本2.1:

S=StringSplit;Total[Flatten@{ToExpression@S[#,LetterCharacter],S[#,DigitCharacter]}&/@S[StringInsert[#,".",First/@StringPosition[#,x_/;UpperCaseQ[x]]],"."]/.{"H"->1,"Li"->3,"Be"->9,"B"->10.8,"C"->12,"N"->14,"O"->16,"F"->19,"Na"->23,"Mg"->24.3,"Al"->27,"Si"->28.1,"P"->31,"S"->32.1,"Cl"->35.5,"K"->39.1,"Ca"->40.1}/.{a_,b_}->a*b]&

说明:查找所有大写字符的位置。在每一个之前放置一个点。在每个点处分割字符串。对于此子字符串列表,请执行以下操作,根据字母对其进行拆分,并根据数字对其进行拆分。对于用字母分割的字符,将字符串转换为数字。对于用数字分隔的数字,请用其分子量替换每种化学物质。对于任何具有分子量和原子数的分子,请将其替换为它们的乘积。他们找到总数。

版本1:

我相信这可以打很多(或完全重写)。我只是想弄清楚该怎么做。(将在早上进行反思。)

F=Flatten;d=DigitCharacter;S=StringSplit;Total@Apply[Times,#,2]&@(Transpose[{F@S[#,d],ToExpression@F@S[#,LetterCharacter]}]&@(#<>If[StringEndsQ[#,d],"","1"]&/@Fold[If[UpperCaseQ[#2],Append[#,#2],F@{Drop[#,-1],Last[#]<>#2}]&,{},StringPartition[#,1]]))/.{"H"->1,"Li"->3,"Be"->9,"B"->10.8,"C"->12,"N"->14,"O"->16,"F"->19,"Na"->23,"Mg"->24.3,"Al"->27,"Si"->28.1,"P"->31,"S"->32.1,"Cl"->35.5,"K"->39.1,"Ca"->40.1}&

说明:首先将字符串分成字符。然后将数组折叠起来,将小写字母和数字连接起来返回其大写字母。接下来,将1附加到任何化学药品上,最后没有数字。然后对数组中的术语进行两次拆分-一次拆分所有数字,另一次拆分所有字母。首先,用摩尔质量替换字母,然后找到这两个列表的点积。


1

Python 3-408字节

这主要是@ovs的解决方案,因为他将其压缩了120多个字节...请参阅下面的初始解决方案。

e='Li Be Na Ca Mg Al Si Cl P S K H B C N O F'.split()
f,g=input(),[]
x=r=0
for i in e:
 if i in f:g+=[(r,eval('6.9 9 23 40.1 24.3 27 28.1 35.5 31 32.1 39.1 1 10.8 12 14 16 19'.split()[e.index(i)]))];f=f.replace(i,' %d- '%r);r+=1
h=f.split()
for c,d in zip(h,h[1:]):
 s=c.find('-')
 if-1<s:
  if'-'in d:
   for y in g:x+=y[1]*(str(y[0])==c[:s])
  else:
   for y in g:x+=y[1]*int(d)*(str(y[0])==c[:s])
print(x)

在线尝试!

Python的3 - 550个548 535字节(失去与压痕计)

@cairdcoinheringaahing节省了10个字节,而ovs节省了3 个字节

我的个人目标是不使用任何正则表达式,并以一种有趣的老式方法来实现它……原来比正则表达式解决方案长350个字节,但它仅使用Python的标准库...

a='Li6.9 Be9. Na23. Ca40.1 Mg24.3 Al27. Si28.1 Cl35.5 P-31. S-32.1 K-39.1 H-1. B-10.8 C-12. N-14. O-16. F-19.'.split()
e,m,f,g,r=[x[:1+(x[1]>'-')]for x in a],[x[2:]for x in a],input(),[],0
for i in e:
 if i in f:g.append((r,float(m[e.index(i)])));f=f.replace(i,' '+str(r)+'- ');r+=1;
h,x=f.split(),0
for i in range(len(h)):
 if '-'in h[i]:
    if '-'in h[i+1]:
     for y in g:x+=y[1]*(str(y[0])==h[i][:h[i].index('-')])
    else:
        for y in g:
         if str(y[0])==h[i][:h[i].index('-')]:x+=(y[1])*int(h[i+1])
 else:1
print(x)  

在线尝试!


如果有人愿意打高尔夫球(使用压痕修复和其他技巧...),它将获得100%的好评,感觉有更好的方法来做...


您可以替换for y in g: if str(y[0])==h[i][:h[i].index('-')]:x+=y[1]for y in g:x+=y[1]*(str(y[0])==h[i][:h[i].index('-')])
caird coinheringaahing

@cairdcoinheringaahing啊,太好了...当我可以使用计算机时更新
Xcoder先生

@ovs非常感谢!记你的答案
Xcoder先生

在Python中,您可以使用分号代替换行符,从而可以节省缩进字节。
帕维尔(Pavel)2013年

@凤凰如果if/for/while下一行没有。由于每行缩进都是这种情况,因此您不能保存字节。
ovs
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.