packages feed

toktok-0.5: Toktok/Trie.hs

module Toktok.Trie where

import Data.Map (Map)
import qualified Data.Map as Map
import Data.Char (toLower, toUpper, isUpper)

data Trie = Trie Bool (Map Char Trie)

emptyTrie = Trie False Map.empty 

mkTrie = fromList

fromList :: [String] -> Trie
fromList [] = emptyTrie
fromList (w:ws) = addWord w $ fromList ws

addWord :: String -> Trie -> Trie
addWord []     (Trie _ m) 
   = Trie True m
addWord (c:cs) (Trie b m) | Map.member c m
   = Trie b $ Map.update (return . addWord cs) c m
addWord (c:cs) (Trie b m) 
   = Trie b $ Map.insert c (addWord cs emptyTrie) m

apply :: Trie -> String -> [[String]]
apply trie = apply' trie []
   where apply' (Trie True _) w [] = [[reverse w]]
         apply' (Trie False _) w [] = []
         apply' (Trie True m) w (c:cs) = (apply' trie "" (c:cs) 
                                          >>= return . (reverse w:))
                                      ++ apply'' m c cs w
         apply' (Trie False m) w (c:cs) = apply'' m c cs w
         apply'' m c cs w = case Map.lookup c m of
                             Nothing -> []
                             Just n -> apply' n (c:w) cs
                         ++ if isUpper c
                             then case Map.lookup (toLower c) m of
                                       Nothing -> []
                                       Just n -> apply' n (toLower c:w) cs
                             else []
         

test :: [[String]]
test = apply t "aabbbc"
  where t = fromList ["a", "ab", "bb", "c", "b"]