Ecuaciones químicas locas

10

Debe obtener una cadena de ecuaciones químicas (sin espacios, solo letras (mayúsculas y minúsculas), números, corchetes y signos matemáticos) del usuario e imprimir la respuesta si la ecuación está equilibrada o no (cualquier par de respuestas positivas / negativas : Sí / No, verdadero / falso, 1/0). Para acortar el código, puede suponer que las cadenas de entrada pueden contener solo estos elementos: Al, Ar, B, Be, C, Cl, Cr, Cu, Fe, H, He, K, N, O, S. Y una cosa más : podría haber -signos. Se trata de matemáticas: +significa suma, -significa resta.

Ejemplos:

Entrada:

C6H5COOH-O2=7CO2+3H2O

Salida:

No

Entrada:

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

Salida:

Yes

Entrada:

2SO2=2SO4-2O2

Salida:

Yes

El código más corto gana.

gthacoder
fuente
¿Estás buscando una función? ¿O un programa que toma entrada de texto y da salida de texto? Si es más tarde, ¿debería tomar y procesar varias líneas? ¿O solo una ecuación por carrera?
MtnViewMark
Relacionado: Balancee las ecuaciones químicas
Peter Taylor
@MtnViewMark Se supone que es un programa. Debería tomar una ecuación por carrera.
gthacoder
Su segundo y tercer ejemplos están equivocados. Creo que querías escribir en 2O2lugar de 202(doscientos dos).
r3mainer
@squeamishossifrage Oh, sí. Seguro. Gracias. La pregunta está actualizada.
gthacoder

Respuestas:

2

Mathematica 152

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

Resultado:

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

Falso

Cierto

Cierto

Trato la fórmula química como un polinomio, p. Ej.

ingrese la descripción de la imagen aquí

Entonces solo cuento los coeficientes.

ybeltukov
fuente
¿Cómo funciona? En su ejemplo, los coeficientes de cada "variable" no se simplifican a cero.
MtnViewMark
@MtnViewMark Más precisamente, cuento poderes con Tr@CoefficientRulesy luego los multiplico por coeficientes con Times@@@. Para O:, 2*2+2*2=4*2para C:, 2*6 = 6*2etc.
ybeltukov
2

Python 2.7, 316 276 caracteres

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)

Hace una gran cantidad de reescritura de expresiones regulares para convertir la ecuación de entrada en algo evalcapaz. Luego verifica la ecuación para cada elemento individualmente.

Por ejemplo, las ecuaciones de ejemplo se reescriben en (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)

Estoy seguro de que hay más golf en la parte de expresiones regulares.

Keith Randall
fuente
2

Haskell, 400 351 308 caracteres

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)

Esto podría tener todo el golf exprimido. ¡No sé si hay otros 100 51 8 caracteres para guardar!

& 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

Aquí está la versión sin golf, en caso de que alguien quiera seguirla. Es un Parsecanalizador de base 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
fuente