Guest User

Untitled

a guest
Dec 14th, 2015
188
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. {-# LANGUAGE FlexibleInstances #-}
  3. --FlexibleInstances чтоб можно было Show (Exp Rational) объявить
  4.  
  5. import Data.List hiding (permutations)
  6. import Control.Monad
  7. import Data.Ratio
  8.  
  9. data Exp a = Plus (Exp a) (Exp a) | Minus (Exp a) (Exp a) |
  10.              Mul (Exp a) (Exp a) | Div (Exp a) (Exp a) | Number a
  11.                                                                            
  12. --объявили рекурсивный тип, описывающий выражения
  13. instance (Show (Exp Rational)) where
  14.   show exp = case exp of
  15.     Number a -> show $ numerator a `div` denominator a
  16.     Plus a b -> "(" ++ show a ++ "+" ++ show b ++ ")"
  17.     Minus a b -> "(" ++ show a ++ "-" ++ show b ++ ")"
  18.     Mul a b -> "(" ++ show a ++ "*" ++ show b ++ ")"
  19.     Div a b -> "(" ++ show a ++ "/" ++ show b ++ ")"
  20.  
  21.  
  22. --вычисляет выражение
  23. eval exp = case exp of
  24.   Number a -> a
  25.   Plus a b -> eval a + eval b
  26.   Minus a b -> eval a - eval b
  27.   Mul a b -> eval a * eval b
  28.   Div a b -> eval a / eval b
  29.  
  30. --возвращает список возможных операций для двух чисел. Для 4, 5 вернет [Plus 4 5..Div 4 5]
  31. operations a b = if eval b == 0 then safeOps else Div a b:safeOps --нужно проверять деление на 0, в таком случае не возвращать Div a b
  32.                                              where safeOps = [Plus a b, Minus a b, Mul a b]
  33. --превращает строку в число типа Exp Rational
  34. parseRational = Number . toRational . read
  35.  
  36. --список возможных выражений для числа, представленного в виде строки
  37. permutations :: String -> [Exp Rational]
  38. permutations [] = []
  39. permutations [x] = [parseRational [x]]
  40. permutations xs = do --здесь рассматриваем список как монаду для удобства
  41.   (y:ys) <- map (map parseRational) $ combinations xs -- возможные комбинации разделений вида [["1, "2"], ["12"]]
  42.   foldM operations y ys --operations - монадическая функция вида a -> m b для монады списков, соответственно применяем монадическую свертку, как бы "сшивая" полученные комбинации разделений всевозможными арифметическими операциями
  43.     where
  44.       combinations :: [a] -> [[[a]]]
  45.       combinations [] = []
  46.       combinations [x] = [[[x]]]
  47.       combinations (x:xs) = map (\(y:ys) -> (x:y):ys) (combinations xs)  ++ map ([x]:) (combinations xs)
  48. main = do
  49.   number <- getLine
  50.   print $  filter ((== 100) . eval) $ permutations number --фильтруем среди всех возможных выражений те, которые дают 100
Advertisement
Add Comment
Please, Sign In to add comment