import Data.Array import Data.Ratio (denominator, numerator) import Text.Parsec type Matrix = Array (Int,Int) Rational type Pair = (Rational,Rational) det :: Matrix -> Rational det m = a*d - b*c where a = m ! (1,1) b = m ! (2,1) c = m ! (1,2) d = m ! (2,2) matrix :: Pair -> Pair -> Matrix matrix (a,c) (b,d) = array ((1,1),(2,2)) [((1,1),a), ((2,1),b), ((1,2),c), ((2,2),d)] solve :: Pair -> Pair -> Pair -> Pair solve target a b = (solA, solB) where coefficients = matrix a b solA = det (matrix target b) / det coefficients solB = det (matrix a target) / det coefficients int :: Rational -> Bool int = (== 1) . denominator maybeSolve :: Pair -> Pair -> Pair -> Maybe Pair maybeSolve target a b = let sol@(a',b') = solve target a b in if int a' && int b' then Just sol else Nothing cost :: Pair -> Pair -> Pair -> Int cost target a b = case maybeSolve target a b of Nothing -> 0 Just (a',b') -> fromIntegral . numerator $ 3*a' + b' cost' :: (Pair,Pair,Pair) -> Int cost' (a, b, target) = cost target a b number :: Parsec String () Rational number = fromInteger . read <$> many digit button :: Parsec String () Pair button = (,) <$ string "Button " <* anyChar <* string ": X+" <*> number <* string ", Y+" <*> number <* newline prize :: Parsec String () Pair prize = (,) <$ string "Prize: X=" <*> ((+ 10000000000000) <$> number) <* string ", Y=" <*> ((+ 10000000000000) <$> number) <* newline parseOne :: Parsec String () (Pair,Pair,Pair) parseOne = (,,) <$> button <*> button <*> prize parseInput :: Parsec String () [(Pair,Pair,Pair)] parseInput = sepBy parseOne newline doParse :: String -> [(Pair,Pair,Pair)] doParse s = case parse parseInput "" s of Left e -> error $ show e Right a -> a main :: IO () main = getContents >>= print . sum . map cost' . doParse