-
Notifications
You must be signed in to change notification settings - Fork 0
/
trie.hs
132 lines (110 loc) · 5.55 KB
/
trie.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import qualified Data.Map as M
import Data.Maybe
import System.Environment
import System.IO
import Prelude hiding (Word)
data Trie = Trie {end :: Bool, children :: M.Map Char Trie}
deriving (Eq, Show)
data Action = Add | Search | Find | Print | Exit
deriving (Eq, Show)
type Word = String
type MyMap = M.Map Char Trie
empty :: Trie
empty = (Trie {end = False, children = M.empty})
insert :: Word -> Trie -> Trie
insert [] (Trie e c) = (Trie True c)
insert wrd@(w:ws) (Trie e c)
| M.lookup w c == Nothing = Trie e (M.insert w (insert ws empty) c)
| otherwise = Trie e (M.insert w (insert ws (fromJust (M.lookup w c))) c)
insertList :: [Word] -> Trie
insertList [] = empty
insertList wrd = foldr insert empty wrd
search :: Word -> Trie -> Bool
search [] (Trie e c) = case e of
True -> True
False -> False
search wrd@(w:ws) (Trie e c)
| M.lookup w c == Nothing = False
| otherwise = search ws (fromJust (M.lookup w c))
getWords :: Trie -> [Word] -- use toList ////// write a function that traverses the trie (while keeping track of where it came from) and also keeps an accumulator which found words are inserted into
getWords (Trie x y) = findWords [] [] [] (M.toList y)
where
findWords :: [(Char, Trie)] -> Word -> [Word] -> [(Char, Trie)] -> [Word]
-- findWords wrd acc (Trie x y) (Trie z t)
-- |
findWords acc wrd lst trace
| trace == [] = lst
| snd (head trace) == empty = findWords [] [] lst (tail trace) -- head of tracei gittikce bosaltmak lazim
| length(returnChildren (head trace)) > 1 = findWords (tail (returnChildren (head trace)) ++ acc) wrd lst (returnChildren (head trace))
| isEnd (snd (head trace)) == True && returnChildren (head trace) == [] = findWords [] [] (lst ++ [ wrd ++ [returnFirstChar trace]] ) (acc ++ tail trace)
| isEnd (snd (head trace)) == True && returnChildren (head trace) /= [] = findWords (acc) [] (lst ++ [ wrd ++ [returnFirstChar trace]] ) (returnChildren (head trace))
| otherwise = findWords (acc) (wrd ++ [fst (head trace)]) lst (returnChildren (head trace))
isEnd :: Trie -> Bool
isEnd (Trie a b) = a
returnFirstChar :: [(Char, Trie)] -> Char
returnFirstChar xs = fst (head xs)
-- returnCharList :: [(Char, Trie)] -> [Char]
-- returnCharList [] = []
-- returnCharList xs = map fst xs
returnChildren :: (Char, Trie) -> [(Char, Trie)]
returnChildren (_, (Trie c d)) = M.toList d
prefix :: String -> Trie -> [String] -- It returns a list of strings that start with the given prefix. If there is no word starting with that prefix, it should return Nothing. You may want to use the getWords function to simplify the implementation of this function.
prefix s t = []
convertAction :: String -> Action
convertAction x = case x of
"a"-> Add
"A" -> Add
"s" -> Search
"S" -> Search
"f" -> Find
"F" -> Find
"p" -> Print
"P" -> Print
"e" -> Exit
"E" -> Exit
_ -> error "There is no such kind of an action"
printList :: [String] -> IO ()
printList [] = return ()
printList xs@(y:ys) = do putStrLn y
printList ys
getInput :: Trie -> IO ()
getInput t = do putStrLn "Enter the action: "
ch <- getLine
let act = convertAction ch
if act == Add
then do putStrLn "Enter word/prefix:"
addWord <- getLine
let o = insert addWord t
putStrLn "New word is added!"
getInput o
else if act == Search
then do putStrLn "Enter word/prefix:"
searchWord <- getLine
if search searchWord t == True
then do putStrLn "Exists in dictionary!"
else
do putStrLn "NOT exist!"
getInput t
else if act == Find
then do putStrLn "Enter word/prefix:"
findWord <- getLine
let prfx = prefix findWord t
if prfx == []
then do putStrLn "No words found with that prefix!"
else
do putStrLn "Found words:"
printList prfx
getInput t
else if act == Print
then do putStrLn "List of words in dictionary:"
let wrds = getWords t
printList wrds
getInput t
else
do putStrLn "Mischief Managed"
main = do putStrLn "a) Add Word"
putStrLn "s) Search Word"
putStrLn "f) Find words with prefix"
putStrLn "p) Print all words"
putStrLn "e) Exit"
getInput empty