import Data.Function
import Data.List
import qualified Data.Set as S

-- 1 - sum of numbers ...
problem_1 :: Int
problem_1 = sum . nub $ [3,6..999] ++ [5,10..999]
problem_1' = sum $ union [3,6..999] [5,10..999]
main = problem_1'

-- bcs.h
import Prelude hiding ((>>=), return)

type Choice a = [a]

choose :: [a] -> Choice a
choose xs = xs

pair456 :: Int -> Choice (Int, Int)
pair456 x = choose [(x, 4), (x, 5), (x, 6)]

join :: Choice (Choice a) -> Choice a
join = concat

-- join $ map pair456 [1,2,3] 
-- [1, 2, 3] >>= pair456
(>>=) :: Choice a -> (a -> Choice b) -> Choice b
choices >>= f = join (map f choices)

return :: a -> Choice a
return x = [x]

makePairs :: Choice (Int, Int)
makePairs = 
  choose [1, 2, 3] >>= (\x ->
  choose [4, 5, 6] >>= (\y ->
  return (x, y)))

mzero :: Choice a
mzero = choose []

guard :: Bool -> Choice ()
guard True  = return ()
guard False = mzero

makePairs' :: Choice (Int,Int)
makePairs' = do
  x <- choose [1,2,3]
  y <- choose [4,5,6]
  guard (x*y == 8)
  return (x,y)
