import System.Environment

-- Aufgabe 11

type Set a = a -> Bool

empty :: Set a
empty _ = False

insert :: Eq a => a -> Set a -> Set a
insert x m y | x==y = True
             | otherwise = m y

remove ::  Eq a => a -> Set a -> Set a
remove  x m y | x==y = False
              | otherwise = m y


isElem :: a -> Set a -> Bool
isElem x m = m x

union :: Set a -> Set a -> Set a
union m1 m2 y = m1 y || m2 y

intersection :: Set a -> Set a -> Set a
intersection m1 m2 y = m1 y && m2 y

difference :: Set a -> Set a -> Set a
difference m1 m2 y = m1 y && not (m2 y)

complement :: Set a -> Set a
complement m y = not (m y)

listToSet :: Eq a => [a] -> Set a
listToSet = foldr insert empty

m1 = listToSet [1..1000000]
m2 = listToSet [5..1500000]

t1 = isElem 3 (m1 `union` m2)
t2 = isElem 13 (m1 `union` m2)
t3 = isElem 23 (m1 `union` m2)
t4 = isElem 3 (m1 `intersection` m2)
t5 = isElem 6 (m1 `intersection` m2)
t6 = isElem 3 (complement m1)
t7 = isElem 13 (complement m1)
t8 = isElem 3 (m1 `difference` m2)
t9 = isElem 7 (m1 `difference` m2)

-- Aufgabe 12

merge :: [Int] -> [Int] -> [Int]
merge []     ys = ys
merge xs     [] = xs
merge (x:xs) (y:ys) | x<y       = x:merge xs (y:ys)
		    | x==y      = x:merge xs ys
		    | otherwise = y:merge (x:xs) ys

hamming :: [Int]
hamming = 1:merge (map (2*) hamming)
                  (merge (map (3*) hamming)
                         (map (5*) hamming))

-- Aufgabe 13

data List a = Nil | Cons a (() -> List a)

headL :: List a -> a
headL (Cons x _) = x

tailL :: List a -> List a
tailL (Cons _ xs) = xs ()

nullL :: List a -> Bool
nullL Nil = True
nullL (Cons _ _) = False

fromL :: Int -> List Int
fromL n = Cons n (\_ -> fromL (n+1))

takeL :: Int -> List a -> List a
takeL n xs | n<=0      = Nil
	   | nullL xs  = Nil
	   | otherwise = Cons (headL xs) (\() -> takeL (n-1) (tailL xs))

toList :: List a -> [a]
toList xs | nullL xs  = []
	  | otherwise = headL xs:toList (tailL xs)

-- Aufgabe 14

sieve :: [Int] -> [Int]
sieve (p:xs) = p:sieve (filter (\x -> x `mod` p >0) xs)

primes :: [Int]
primes = sieve [2..]

lessPrimes :: IO ()
lessPrimes = do
  putStr "Bitte Zahl eingeben: "
  str <- getLine
  case reads str of
    ((n,""):_) -> print (takeWhile (<n) primes)
    _          -> do
        putStrLn "Bitte eine Zahl eingeben!"
        lessPrimes

diamond :: Int -> IO ()
diamond (n+1) = let lines = map dreieckLine [0..n] in
                  putStrLn $ unlines $ lines ++ tail (reverse lines)
  where dreieckLine :: Int -> String
        dreieckLine 0     = replicate n ' ' ++ "*"
	dreieckLine m = replicate (n-m) ' ' ++ "*" ++
                        replicate (2*m-1) ' ' ++ "*"

dia :: Int -> IO ()
dia 1 = putStrLn "*"
dia (n+1) = dia' n
  where dia' :: Int -> IO ()
        dia' 0 = putStr ("*"++replicate (2*n-1) ' '++"*\n")
	dia' m = 
          let a = putStr (if n==m 
                            then replicate (n) ' '++"*\n"
                            else replicate (m) ' '++"*" ++ 
                                 replicate (2*(n-m)-1) ' ' ++"*\n")
                  in
                    a >> dia' (m-1) >> a

htmlEncoder :: String -> String -> IO ()
htmlEncoder inFile outFile = do
  str <- readFile inFile
  writeFile outFile (umlFy str)
  where umlFy :: String -> String
	umlFy ('\195':'\164':str) = "&auml;"++umlFy str
	umlFy ('\195':'\182':str) = "&ouml;"++umlFy str
	umlFy ('\195':'\188':str) = "&uuml;"++umlFy str
	umlFy ('\195':'\132':str) = "&Auml;"++umlFy str
	umlFy ('\195':'\150':str) = "&Ouml;"++umlFy str
	umlFy ('\195':'\156':str) = "&Uuml;"++umlFy str
	umlFy ('\195':'\159':str) = "&szlig;"++umlFy str
	umlFy (c:str)             = c:umlFy str
	umlFy ""                  = ""


main :: IO ()
main = do
  (i:o:_) <- getArgs
  htmlEncoder i o
