Verrückte chemische Gleichungen

10

Sie sollten vom Benutzer eine Reihe chemischer Gleichungen (keine Leerzeichen, nur Buchstaben (Groß- und Kleinbuchstaben), Zahlen, Klammern und mathematische Zeichen) erhalten und die Antwort ausdrucken, ob die Gleichung ausgeglichen ist oder nicht (ein Paar positiver / negativer Antworten) : Ja / Nein, wahr / falsch, 1/0). Um den Code zu verkürzen, können Sie davon ausgehen, dass Eingabezeichenfolgen nur die folgenden Elemente enthalten können: Al, Ar, B, Be, C, Cl, Cr, Cu, Fe, H, He, K, N, O, S. Und noch etwas : Es könnte -Anzeichen geben. Alles dreht sich um Mathematik: +bedeutet Addition, -bedeutet Subtraktion.

Beispiele:

Eingang:

C6H5COOH-O2=7CO2+3H2O

Ausgabe:

No

Eingang:

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

Ausgabe:

Yes

Eingang:

2SO2=2SO4-2O2

Ausgabe:

Yes

Der kürzeste Code gewinnt.

gthacoder
quelle
Suchen Sie eine Funktion? Oder ein Programm, das Texteingabe und Textausgabe übernimmt? Wenn dies später der Fall ist, sollten mehrere Zeilen benötigt und verarbeitet werden? Oder nur eine Gleichung pro Lauf?
MtnViewMark
Verwandte: Balance chemische Gleichungen
Peter Taylor
@MtnViewMark Es soll ein Programm sein. Es sollte eine Gleichung pro Lauf erforderlich sein.
Gthacoder
Ihr zweites und drittes Beispiel sind falsch. Ich denke, Sie wollten 2O2statt 202(zweihundertzwei) tippen .
r3mainer
@squeamishossifrage Oh ja. Sicher. Vielen Dank. Frage wird aktualisiert.
Gthacoder

Antworten:

2

Mathematica 152

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

Ergebnis:

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

Falsch

Wahr

Wahr

Ich behandle die chemische Formel als Polynom, z

Geben Sie hier die Bildbeschreibung ein

Dann zähle ich einfach die Koeffizienten.

ybeltukov
quelle
Wie funktioniert das? In Ihrem Beispiel vereinfachen sich die Koeffizienten jeder "Variablen" nicht auf Null.
MtnViewMark
@MtnViewMark Genauer gesagt zähle ich Potenzen mit Tr@CoefficientRulesund multipliziere sie dann mit Koeffizienten mit Times@@@. Für O: 2*2+2*2=4*2, für C: 2*6 = 6*2usw.
ybeltukov
2

Python 2.7, 316 276 Zeichen

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)

Es wird viel Regex-Rewriting durchgeführt, um die Eingabegleichung in etwas fähiges umzuwandeln eval. Anschließend wird die Gleichung für jedes Element einzeln überprüft.

Zum Beispiel werden die Beispielgleichungen in (die tVariable) umgeschrieben :

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

Ich bin sicher, es gibt mehr Golf auf dem Regex-Teil.

Keith Randall
quelle
2

Haskell, 400 351 308 Zeichen

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)

Dies könnte den ganzen Golf herausgequetscht haben. Ich weiß nicht, ob noch 100 51 8 Zeichen gespeichert werden müssen!

& 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

Hier ist die ungolf'd Version, falls jemand mitmachen möchte. Es ist ein einfacher Parsecbasierter Parser:

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
quelle