Божевільні хімічні рівняння


10

Ви повинні отримати рядок хімічного рівняння (без пробілів, лише літери (великі та малі регістри), цифри, дужки та математичні знаки) від користувача та надрукувати відповідь, якщо рівняння врівноважене чи ні (будь-яка пара позитивних / негативних відповідей : Так / Ні, правда / хибність, 1/0). Щоб скоротити код, ви можете припустити, що вхідні рядки можуть містити лише такі елементи: Al, Ar, B, Be, C, Cl, Cr, Cu, Fe, H, He, K, N, O, S. І ще одне : можуть бути -знаки. Вся справа в математиці: +означає додавання, -означає віднімання.

Приклади:

Вхід:

C6H5COOH-O2=7CO2+3H2O

Вихід:

No

Вхід:

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

Вихід:

Yes

Вхід:

2SO2=2SO4-2O2

Вихід:

Yes

Виграє найкоротший код.


Шукаєте функцію? Або програма, яка приймає текст і надає текст? Якщо пізніше, це повинно зайняти та обробити кілька рядків? Або лише одне рівняння за пробіг?
MtnViewMark


@MtnViewMark Це має бути програма. Він повинен приймати одне рівняння на пробіг.
gthacoder

Ваш другий і третій приклади помиляються. Я думаю, ти мав намір ввести 2O2замість 202(двісті дві).
r3mainer

@squeamishossifrage О так. Звичайно. Дякую. Питання оновлено.
gthacoder

Відповіді:


2

Математика 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

@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

Ось версія ungolf'd на випадок, якщо хтось захоче слідувати далі. Це простий 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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.