Commits

Luke Plant committed fa08e5f

Reorganised code

Comments (0)

Files changed (1)

 import qualified Data.ByteString.Char8 as B
 import qualified Data.Map as Map
 
--- store words in a tree where the nodes are labelled as numbers
+--
+-- Definitions
+--
 
 letters = [ ('0', "")
           , ('1', "")
           , ('9', "WXYZ")
           ]
 
+--
+-- General utilities
+--
+
 lettersMap :: Map.Map Char [Char]
 lettersMap = Map.fromList letters
 
 getNumber :: Char -> Maybe Char
 getNumber char = Map.lookup (toUpper char) numbersMap
 
--- TODO - this whole datastructure should be strict
--- and read in strictly
-
 data WordTree = Node { nodeLabel :: Char           -- digit
                      , nodeSubForest :: [WordTree] -- children
                      , nodeWords :: [B.ByteString] -- words that correspond to this node
                      } deriving (Eq, Read, Show)
 
+
+ -- Look up a char in the sub forests, and return ([matching WordTree], [non-matching WordTree])
+subForestLookup :: Char -> WordTree -> ([WordTree],[WordTree])
+subForestLookup char tree = partition (\n -> nodeLabel n == char) $ nodeSubForest tree
+
+--
+-- Building the tree
+--
+
 startNode = Node { nodeLabel = 'X' -- never used
                  , nodeSubForest = []
                  , nodeWords = []
       buildWordTree' (w:ws) tree = buildWordTree' ws (addWord w w tree)
 
 
- -- Look up a char in the sub forests, and return ([matching WordTree], [non-matching WordTree])
-subForestLookup :: Char -> WordTree -> ([WordTree],[WordTree])
-subForestLookup char tree = partition (\n -> nodeLabel n == char) $ nodeSubForest tree
-
 addWord :: B.ByteString -- ^ remaining characters
         -> B.ByteString -- ^ whole word
         -> WordTree     -- ^ input tree
                      in tree { nodeSubForest = node' : others }
 
 
+--
+-- Search the tree
+--
+
 -- | Find words that correspond exactly to the digits supplied
 findWords :: B.ByteString -- ^ the string of digits
           -> WordTree
                  [] -> []
                  (n:_) -> findWords ds n
 
-getWords :: IO [B.ByteString]
-getWords = B.readFile "/usr/share/dict/words" >>= (return . (filter (\x -> B.length x > 1)) . B.lines)
-
-countNodes t = 1 + (sum $ map countNodes (nodeSubForest t))
-
-countWords t = length (nodeWords t) + (sum $ map countWords (nodeSubForest t))
-
-main = do
-  ws <- getWords
-  let wordTree = buildWordTree ws
-  putStr "Words: "
-  print (countWords wordTree)
-  putStr "Nodes: "
-  print (countNodes wordTree)
-  mainLoop wordTree
-
-mainLoop wordTree = do
-  putStrLn "Enter phone number: "
-  number' <- getLine
-  putStrLn "Matches: "
-  let number = filter isDigit number'
-  let combos = findCombos (B.pack number) wordTree
-  case length combos of
-    0 -> putStrLn " [None]"
-    _ -> mapM_ B.putStrLn $ map showCombo combos
-  putStrLn ""
-
-  mainLoop wordTree
-
--- TODO
 --
--- * search for combinations to get a 'memorable' version of a phone number
-
+-- Search for combos
+--
 
 type Combo = [Segment]
 type Segment = B.ByteString
 
-
 findCombos :: B.ByteString
            -> WordTree
            -> [Combo]
     allDigits = not . hasWord
 
 showCombo = B.intercalate (B.pack "-")
+
+
+--
+-- Main
+--
+
+getWords :: IO [B.ByteString]
+getWords = B.readFile "/usr/share/dict/words" >>= (return . (filter (\x -> B.length x > 1)) . B.lines)
+
+countNodes t = 1 + (sum $ map countNodes (nodeSubForest t))
+
+countWords t = length (nodeWords t) + (sum $ map countWords (nodeSubForest t))
+
+
+main = do
+  ws <- getWords
+  let wordTree = buildWordTree ws
+  putStr "Words: "
+  print (countWords wordTree)
+  putStr "Nodes: "
+  print (countNodes wordTree)
+  mainLoop wordTree
+
+mainLoop wordTree = do
+  putStrLn "Enter phone number: "
+  number' <- getLine
+  putStrLn "Matches: "
+  let number = filter isDigit number'
+  let combos = findCombos (B.pack number) wordTree
+  case length combos of
+    0 -> putStrLn " [None]"
+    _ -> mapM_ B.putStrLn $ map showCombo combos
+  putStrLn ""
+
+  mainLoop wordTree