주어진 화합물의 미스터를 찾아라!


12

도전

화학 물질의 공식이 주어지면 화합물 의 M r 을 산출하십시오 .

방정식

화합물의 각 원소 다음에는 화합물에서 상기 원자의 수를 나타내는 숫자가 뒤 따른다. 숫자가 없으면 화합물에 해당 원자 중 하나만 있습니다.

몇 가지 예는 다음과 같습니다.

  • 에탄올 (C 2 H 6 O) C2H6O은 두 개의 탄소 원자, 6 개의 수소 원자 및 1 개의 산소 원자가있는 곳입니다.
  • 수산화 마그네슘 (MgO 2 H 2 ) MgO2H2은 1 개의 마그네슘 원자, 2 개의 산소 원자 및 2 개의 수소 원자가 존재하는 곳에있을 것이다 .

대괄호를 다룰 필요는 없으며 각 요소는 수식에 한 번만 포함됩니다.

대부분의 사람들은 아마도 가장 편한 순서를 고수 할 것이지만, 엄격한 주문 시스템은 없습니다. 예를 들어, 물은 H2O또는 로 제공 될 수 있습니다 OH2.

M r

참고 : 여기서 공식 질량은 분자 질량과 같다고 가정합니다

분자 질량 인 화합물 의 M r 은 분자 내 원자원자량 의 합이다 .

지지해야하는 유일한 원소와 원자량의 소수점 이하 1 자리 (고귀한 가스는 제외하고 수소에서 칼슘까지)는 다음과 같습니다. 그들은 또한 여기 에서 찾을 수 있습니다

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 은 소수점 1 자리까지입니다.

규칙

원소 또는 화학 물질 데이터에 접근하는 빌트인은 허용되지 않습니다 (죄송합니다 Mathematica)

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

승리

바이트 단위의 최단 코드가 이깁니다.

이 게시물은 caird coinheringaahing의 허락하에 채택 되었습니다 . (포스트 삭제)


다음과 같은 수량자를 처리해야 2H2O합니까?
Mr. Xcoder 2016 년

6
궁금한 점은 Mathematica 솔루션 (53 바이트)입니다.NumberForm[#&@@#~ChemicalData~"MolecularMass",{9,1}]&
JungHwan Min

답변:


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

이것은 내가 본 것 중 가장 긴 젤리 답변 중 하나이지만, 현재 두 번째 프로그램의 절반보다 짧습니다.
그리폰

6

파이썬 3 ,  189182168  바이트

-14에서 해시를 사용하여 바이트 저스틴 마리너의 자바 스크립트 (ES6) 대답을 .

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이는 파이썬 문자열이 거짓이기 때문에 논리로 달성됩니다 int(n or 1).

요소 문자열은 첫 번째 문자와 마지막 문자 서수를 곱하여 고유 번호를 부여합니다 (일반적으로 S 또는 C와 동일하지만 Cl, C, Ca 및 Na를 구분해야하므로 하나만 사용할 수 없음) 캐릭터).

그런 다음이 숫자는 모듈로 공간을 검색하여 찾은 [0,18]의 훨씬 작은 범위를 커버하도록 해시됩니다 %1135%98%19. 예를 들어 , 곱하기 곱하는 "Cl"서수와을 67가지며 108, 어떤 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]
is 35.5, 원자량 Cl, 그런 다음 이러한 요소 수 (위에서 찾은)를 곱합니다.

그런 다음이 제품을 사용하여 함께 추가합니다 sum(...).


당신은 천재입니다 ... 350 바이트 이상 나를 능가했습니다
Mr. Xcoder

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

자바 스크립트 (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 answer 에서 영감을 얻어 각 요소에 고유 번호를 부여하고 해당 숫자를 더 작은 범위로 해시하는 방법을 설명했습니다.

요소는 기본 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>


오, 당신의 길은 나에게 몇 바이트를 절약 할 것이라고 생각합니다!
Jonathan Allan

2

클로저, 198 194 바이트

업데이트 :보다 낫 for습니다 reduce.

#(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

파이썬 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

파이썬 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)

온라인으로 사용해보십시오!

파이썬 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('-')])
coinheringaahing 케어 드

@cairdcoinheringaahing 아, 좋아 ... 컴퓨터에 액세스 할 때 업데이트
Mr. Xcoder

@ovs 감사합니다! 답변에서 당신을 인정
Mr. Xcoder

파이썬에서는 줄 바꿈 대신 세미콜론을 사용하여 들여 쓰기에 바이트를 저장할 수 있습니다.
Pavel

@Phoenix if/for/while는 다음 줄에 없으면 없습니다 . 이것은 들여 쓰기 된 모든 줄에서 발생하므로 바이트를 저장할 수 없습니다.
ovs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.