-- converts the result of parseFloor into a numberical representation of
-- items conforming with the description of ItemSet
-- returns a pair containing the list of items on each floor and the map of
-- name -> bit pos / 2 associations
dataToNumeric :: [[(Char, String)]] -> ([[Item]], M.Map String Int)
dataToNumeric lst = let
        -- assigns each element a unique number starting from 0
        helper :: [(Char, String)] -> M.Map String Int -> M.Map String Int
        helper [] m = m
        helper ((_, name):xs) m = case M.lookup name m of
            Just _ -> helper xs m
            Nothing -> helper xs (M.insert name (M.size m) m)

        names = helper (concat lst) M.empty

        -- converts an item generated by parseItemList into a Item
        convert :: (Char, String) -> Item
        convert ('G', name) = 1 `shift` (2 * M.findWithDefault 0 name names)
        convert ('M', name) = 1 `shift` (1 + 2 * M.findWithDefault 0 name names)
        convert x = error $ show x
    in
        (map (map convert) lst, names)
dataToNumeric :: [[(Char, String)]] -> ([[Item]], M.Map String Int)
dataToNumeric lst = let
        -- assigns each element a unique number starting from 0
        helper :: [(Char, String)] -> M.Map String Int -> M.Map String Int
        helper [] m = m
        helper ((_, name):xs) m = case M.lookup name m of
            Just _ -> helper xs m
            Nothing -> helper xs (M.insert name (M.size m) m)

        names = helper (concat lst) M.empty

        -- converts an item generated by parseItemList into a Item
        convert :: (Char, String) -> Item
        convert ('G', name) = 1 `shift` (2 * M.findWithDefault 0 name names)
        convert ('M', name) = 1 `shift` (1 + 2 * M.findWithDefault 0 name names)
        convert x = error $ show x
    in
        (map (map convert) lst, names)
dataToNumeric lst = let
        -- assigns each element a unique number starting from 0
        helper :: [(Char, String)] -> M.Map String Int -> M.Map String Int
        helper [] m = m
        helper ((_, name):xs) m = case M.lookup name m of
            Just _ -> helper xs m
            Nothing -> helper xs (M.insert name (M.size m) m)

        names = helper (concat lst) M.empty

        -- converts an item generated by parseItemList into a Item
        convert :: (Char, String) -> Item
        convert ('G', name) = 1 `shift` (2 * M.findWithDefault 0 name names)
        convert ('M', name) = 1 `shift` (1 + 2 * M.findWithDefault 0 name names)
        convert x = error $ show x
    in
        (map (map convert) lst, names)