import Data.Maybe import Data.List import qualified Data.Map as Map -- |Sort list by function result (don't use Schwarznegian transform!) sortOn f = sortBy (map2cmp f) -- |Group list by function result groupOn f = groupBy (map2eq f) -- |Sort and Group list by function result sort_and_groupOn f = groupOn f . sortOn f -- Utility functions for list operations keyval f x = (f x, x) -- |Return pair containing computed key and original value map2cmp f x y = (f x) `compare` (f y) -- |Converts "key_func" to "compare_func" map2eq f x y = (f x) == (f y) -- |Converts "key_func" to "eq_func" data Title = Title { id :: !Int , title :: String } deriving (Show,Eq,Ord) data Elem = Elem { count :: !Int , titles :: [Title] } deriving (Show,Eq,Ord) main = do database <- readFile "database" -- database is "A big fish\nRed eye\n..." let k = zip [1..] . lines -- k is [(1,"A big fish"), (2,"Red eye"), ...] m = concatMap (\(n,str) -> map (\w -> (w,Title n str)) (words str)) -- m is [("A", Title 1 "A big fish"), ("big", Title 1 "A big fish"), -- ("fish", Title 1 "A big fish"), ("Red", Title 2 "Red eye")...] g = sort_and_groupOn fst -- g is [[("A", Title 1 "A big fish"), ("A", Title 66 "A silly thing")], -- [("big", Title 77 "A big fish"), ("big", Title 88 "Bad big boys")]...] h = map (\list -> let w = fst (head list) -- "A" titles = map snd list -- [Title 1 "A big fish", Title 66 "A silly thing"] size = length list -- 2 in (w, Elem size titles)) -- h is [("A", (Elem 2 [Title 1 "A big fish", Title 66 "A silly thing"]))... ] fm = (Map.fromDistinctAscList .h.g.m.k) database -- fm maps "A" to (Elem 2 [Title 1 "A big fish", Title 66 "A silly thing"]) let m = sortOn count . catMaybes . map (`Map.lookup` fm) . words -- m is [Elem 2 [Title 1 "A big fish", Title 66 "A silly thing"], Elem 5 [...], ...] title1 = title . head . titles . head -- title1 is "A big fish", a closest-matching title new <- readFile "new" putStr$ (unlines . map (title1 . m) . filter (not.null) . lines) new