クレイジーな化学方程式


10

ユーザーから化学式の文字列(スペースなし、文字(大文字と小文字)のみ、数字、角かっこ、数学記号)を取得し、方程式がバランスしているかどうか(正/負の任意のペアの答え)を出力する必要があります:はい/いいえ、true / false、1/0)。アル中、Ar、B、う、C、Clで、クロム、銅、鉄、H、彼、K、N、O、Sと:コードを短くするには、その入力文字列がこれらの要素のみ含めることができると仮定することができますもう一つの:-兆候がある可能性があります。それはすべて数学についてです:+加算を-意味し、減算を意味します。

例:

入力:

C6H5COOH-O2=7CO2+3H2O

出力:

No

入力:

2Fe(CN)6+2SO2+202=Fe2(SO4)2+6C2N2

出力:

Yes

入力:

2SO2=2SO4-2O2

出力:

Yes

最短のコードが優先されます。


機能をお探しですか?または、テキスト入力を受け取り、テキスト出力を行うプログラムですか?後者の場合、複数の行を取得して処理する必要がありますか?または実行ごとに1つの方程式だけですか?
— MtnViewMark 2014年


@MtnViewMarkプログラムであることを想定しています。実行ごとに1つの方程式が必要です。
— gthacoder 2014年

2番目と3番目の例は間違っています。(200)の2O2代わりにタイプするつもりだったと思います202。
— r3mainer 2014年

@squeamishossifrageああ、そうです。承知しました。ありがとうございました。質問を更新しました。
— gthacoder 2014年

回答:


2

Mathematica 152

f=Times@@@Tr@CoefficientRules@ToExpression@(r=StringReplace)[r[
#<>")",{"="->"-(",x:_?LetterQ|")"~~y_?DigitQ:>x<>"^"<>y}],x_?UpperCaseQ:>" "<>x]⋃{}=={0}&

結果:

f@"C6H5COOH-O2=7CO2+3H2O"
f@"2Fe(CN)6+2SO2+2O2=Fe2(SO4)2+6C2N2"
f@"2SO2=2SO4-2O2"

誤り

本当

本当

化学式を多項式として扱います。

ここに画像の説明を入力してください

次に、係数を数えます。


それはどのように機能しますか?あなたの例では、各「変数」の係数はゼロに単純化されていません。
— MtnViewMark 2014年

@MtnViewMarkより正確には、で累乗をカウントしTr@CoefficientRules、で係数を乗算しTimes@@@ます。の場合O:2*2+2*2=4*2、の場合C:2*6 = 6*2など
— ybeltukov

2

Python 2.7、316 276文字

import re
r=re.sub
x='(^|[=+-])'
y=r'\1+\2'
z='(\w)([A-Z(])'
t=r('=','==',r(z,y,r(z,y,r('([A-Za-z)])(\d)',r'\1*\2',r('([=+-]|$)',r')\1',r(x+'(\d+)',r'\1\2*(',r(x+'([A-Z])',r'\1(\2',raw_input())))))))
E=re.findall('[A-Za-z]+',t)
print all(eval(t,{f:f==e for f in E})for e in E)

入力方程式を可能なものに変換するために、多くの正規表現書き換えを行いますeval。次に、各要素の方程式を個別にチェックします。

たとえば、方程式の例は(t変数)に書き換えられます。

(C*6+H*5+C+O+O+H)-(O*2)==7*(C+O*2)+3*(H*2+O)
2*(Fe+(C+N)*6)+2*(S+O*2)+2*(O*2)==(Fe*2+(S+O*4)*2)+6*(C*2+N*2)
2*(S+O*2)==2*(S+O*4)-2*(O*2)

正規表現の部分にはもっと多くのゴルフがあると確信しています。


2

Haskell、400 351 308文字

import Data.List
import Text.Parsec
(&)=fmap
r=return
s=string
l f b=(>>=(&b).f)
x=(=<<).replicate
m=sort&chainl1(l x(concat&many1(l(flip x)n i))n)((s"+">>r(++))<|>(s"-">>r(\\)))
i=between(s"(")(s")")m<|>(:[])&(l(:)(many lower)upper)
n=option 1$read&many1 digit
main=getContents>>=parseTest(l(==)(s"=">>m)m)

これは、ゴルフのすべてを圧迫している可能性があります。保存できる別の100 51 8文字があるかどうかわかりません!

& echo 'C6H5COOH-O2=7CO2+3H2O' | runhaskell Chemical.hs
False

& echo '2Fe(CN)6+2SO2+2O2=Fe2(SO4)2+6C2N2' | runhaskell Chemical.hs
True

& echo '2SO2=2SO4-2O2' | runhaskell Chemical.hs
True

これは、誰かがフォローしたい場合に備えて、ゴルフ版ではないバージョンです。シンプルなParsecベースのパーサーです:

import Control.Applicative ((<$>), (<*>))
import Data.List
import Text.Parsec
import Text.Parsec.String (Parser)

type Atom = String

{- golf'd as x -}
multiple :: Int -> [Atom] -> [Atom]
multiple n = concat . replicate n

{- golf'd as m -}
chemicals :: Parser [Atom]
chemicals = sort <$> chainl1 molecules op
  where
    op :: Eq a => Parser ([a] -> [a] -> [a])
    op = (char '+' >> return (++))
     <|> (char '-' >> return (\\))

    molecules :: Parser [Atom]
    molecules = multiple <$> number <*> terms

    terms :: Parser [Atom]
    terms = concat <$> many1 term

    term :: Parser [Atom]
    term = flip multiple <$> item <*> number

{- gofl'd as i -}
item :: Parser [Atom]
item = between (char '(') (char ')') chemicals
   <|> (:[]) <$> atom
  where
    atom :: Parser Atom
    atom = (:) <$> upper <*> many lower

{- gofl'd as n -}
number :: Parser Int
number = option 1 $ read <$> many1 digit

{- gofl'd as main -}
main :: IO ()
main = getContents >>= parseTest chemEquality
  where
    chemEquality :: Parser Bool
    chemEquality = (==) <$> chemicals <*> (char '=' >> chemicals)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.