Advertisement
NLinker

Haskell russian DSL

Feb 10th, 2022
1,441
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import Data.List
  2.  
  3. {- Задача. Есть некоторое количество участников, которых нужно разбить
  4. на две равные команды.-}
  5.  
  6. участников = ["Антон", "Маша", "Дима", "Юра", "Андрей", "Инна", "Олег", "Света"]
  7.  
  8. {- При этом некоторые пары участников хотят обязательно
  9. быть в одной команде, а некоторые - обязательно в разных. -}
  10.  
  11. будутВместе = [("Антон", "Маша"), ("Олег", "Света")]
  12. будутПорознь = [("Андрей", "Инна"), ("Олег", "Юра")]
  13.  
  14. {- Нужно найти все подходящие варианты разбиений. -}
  15.  
  16. main = показать $ подходящие `из` всехРазбиений участников
  17.  
  18. {- Немножко русских синонимов для стандартных функций. -}
  19.  
  20. размер = length
  21. будетВ = (:)
  22. infixr 5 `будетВ`
  23. но = flip ($)
  24. infixl 6 `но`
  25. из = filter
  26. в = elem
  27. иначе = otherwise
  28. пополам = (`quot` 2)
  29. когдаИ True True = True
  30. когдаИ False False = True
  31. когдаИ _ _ = False
  32. наоборот = not
  33. одно `либо` другое = одно `когдаИ` другое `но` наоборот
  34. все = all
  35. черезЗапятую = intercalate ", "
  36. показать =
  37.     mapM_ $ \(первые, вторые) ->
  38.         putStrLn $ черезЗапятую первые ++ " и их оппоненты " ++ черезЗапятую вторые
  39. отобрать = filter
  40.  
  41. {- Ну и собственно простой переборный алгоритм. -}
  42.  
  43. ктоХочет вместе команде =
  44.     все (\(первый, второй) ->
  45.         (первый `в` команде) `когдаИ` (второй `в` команде)) вместе
  46.  
  47. ктоНеХочет вместе команде =
  48.     все (\(первый, второй) ->
  49.         (первый `в` команде) `либо` (второй `в` команде)) вместе
  50.  
  51. размерКоманды = размер участников `но` пополам
  52.  
  53. всехРазбиений = безДублей . разбиения [] [] where
  54.     безДублей [] = []
  55.     безДублей (вотЭта:пропустить:остальных) =
  56.         вотЭта `будетВ` остальных `но` безДублей
  57.     разбиения первой второй другие
  58.         | размер первой == размерКоманды = [(первой, второй ++ другие)]
  59.         | размер второй == размерКоманды = [(первой ++ другие, второй)]
  60.         | иначе = let новый : остальные = другие in.
  61.             разбиения (новый `будетВ` первой) второй остальные ++
  62.             разбиения первой (новый `будетВ` второй) остальные
  63.  
  64. подходящие (вПервой, воВторой) =
  65.     ктоХочет будутВместе вПервой &&
  66.     ктоНеХочет будутПорознь вПервой
  67.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement