import Data.List
{- Задача. Есть некоторое количество участников, которых нужно разбить
на две равные команды.-}
участников = ["Антон", "Маша", "Дима", "Юра", "Андрей", "Инна", "Олег", "Света"]
{- При этом некоторые пары участников хотят обязательно
быть в одной команде, а некоторые - обязательно в разных. -}
будутВместе = [("Антон", "Маша"), ("Олег", "Света")]
будутПорознь = [("Андрей", "Инна"), ("Олег", "Юра")]
{- Нужно найти все подходящие варианты разбиений. -}
main = показать $ подходящие `из` всехРазбиений участников
{- Немножко русских синонимов для стандартных функций. -}
размер = length
будетВ = (:)
infixr 5 `будетВ`
но = flip ($)
infixl 6 `но`
из = filter
в = elem
иначе = otherwise
пополам = (`quot` 2)
когдаИ True True = True
когдаИ False False = True
когдаИ _ _ = False
наоборот = not
одно `либо` другое = одно `когдаИ` другое `но` наоборот
все = all
черезЗапятую = intercalate ", "
показать =
mapM_ $ \(первые, вторые) ->
putStrLn $ черезЗапятую первые ++ " и их оппоненты " ++ черезЗапятую вторые
отобрать = filter
{- Ну и собственно простой переборный алгоритм. -}
ктоХочет вместе команде =
все (\(первый, второй) ->
(первый `в` команде) `когдаИ` (второй `в` команде)) вместе
ктоНеХочет вместе команде =
все (\(первый, второй) ->
(первый `в` команде) `либо` (второй `в` команде)) вместе
размерКоманды = размер участников `но` пополам
всехРазбиений = безДублей . разбиения [] [] where
безДублей [] = []
безДублей (вотЭта:пропустить:остальных) =
вотЭта `будетВ` остальных `но` безДублей
разбиения первой второй другие
| размер первой == размерКоманды = [(первой, второй ++ другие)]
| размер второй == размерКоманды = [(первой ++ другие, второй)]
| иначе = let новый : остальные = другие in.
разбиения (новый `будетВ` первой) второй остальные ++
разбиения первой (новый `будетВ` второй) остальные
подходящие (вПервой, воВторой) =
ктоХочет будутВместе вПервой &&
ктоНеХочет будутПорознь вПервой
Comments
0 B
|👍
/👎
0 B
|👍
/👎