Équations chimiques folles

10

Vous devez obtenir une chaîne d'équation chimique (pas d'espaces, uniquement des lettres (majuscules et minuscules), des chiffres, des crochets et des signes mathématiques) de l'utilisateur et imprimer la réponse si l'équation est équilibrée ou non (toute paire de réponses positives / négatives : Oui / Non, vrai / faux, 1/0). Pour raccourcir le code, vous pouvez supposer que les chaînes d'entrée ne peuvent contenir que ces éléments: Al, Ar, B, Be, C, Cl, Cr, Cu, Fe, H, He, K, N, O, S. Et encore une chose : il pourrait y avoir des -signes. Tout est question de mathématiques: +signifie addition, -signifie soustraction.

Exemples:

Contribution:

C6H5COOH-O2=7CO2+3H2O

Production:

No

Contribution:

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

Production:

Yes

Contribution:

2SO2=2SO4-2O2

Production:

Yes

Le code le plus court gagne.

gthacoder
la source
Cherchez-vous une fonction? Ou un programme qui prend la saisie de texte et donne une sortie de texte? Si ce dernier, doit-il prendre et traiter plusieurs lignes? Ou juste une équation par course?
MtnViewMark
Connexes: équilibrer les équations chimiques
Peter Taylor
@MtnViewMark Il est censé être un programme. Cela devrait prendre une équation par cycle.
gthacoder
Vos deuxième et troisième exemples sont erronés. Je pense que vous vouliez taper 2O2au lieu de 202(deux cent deux).
r3mainer
@squeamishossifrage Oh, oui. Sûr. Je vous remercie. La question est mise à jour.
gthacoder

Réponses:

2

Mathematica 152

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

Résultat:

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

Faux

Vrai

Vrai

Je traite la formule chimique comme un polynôme, par exemple

entrez la description de l'image ici

Ensuite, je compte juste les coefficients.

ybeltukov
la source
Comment ça marche? Dans votre exemple, les coefficients de chaque "variable" ne se simplifient pas à zéro.
MtnViewMark
@MtnViewMark Plus précisément, je compte les puissances avec Tr@CoefficientRulespuis je les multiplie par des coefficients avec Times@@@. Pour O: 2*2+2*2=4*2pour C: 2*6 = 6*2, etc.
ybeltukov
2

Python 2.7, 316 276 caractères

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)

Il fait beaucoup de réécriture regex pour convertir l'équation d'entrée en quelque chose de evalcapable. Il vérifie ensuite l'équation pour chaque élément individuellement.

Par exemple, les équations d'exemple réécrivent dans (la tvariable):

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

Je suis sûr qu'il y a plus de golf sur la partie regex.

Keith Randall
la source
2

Haskell, 400 351 308 caractères

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)

Cela pourrait avoir tout le golf hors de lui. Je ne sais pas s'il y a encore 100 51 8 caractères à sauver!

& 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

Voici la version non golfée, au cas où quelqu'un voudrait suivre. Il s'agit d'un Parsecanalyseur basé simple :

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)
MtnViewMark
la source