Untitled
unknown
haskell
5 years ago
3.2 kB
11
Indexable
module Ch11.Phone where
import Data.Char (toLower, isUpper)
import Data.List (group, sort)
import Ch11.Adt (splitWords)
data Key = One
| Star
| TextKey Char [Char]
instance Show Key where
show One = "1"
show Star = "*"
show (TextKey c _) = c : ""
type Phone = [Key]
phoneKb :: Phone
phoneKb = [One, Star, TextKey '#' ".,",
TextKey '2' "abc", TextKey '3' "def", TextKey '4' "ghi"
, TextKey '5' "jkl", TextKey '6' "mno", TextKey '7' "pqrs"
, TextKey '8' "tuv", TextKey '9' "wxyz", TextKey '0' "+ _"
]
type Presses = Int
-- function names are retarded, I kept the ones from the book
-- calculate key sequence to press to reach to given character
reverseTaps :: Phone -> Char -> [(Key, Presses)]
reverseTaps kb c
| isUpper c = (Star, 1) : [(letterPresses kb $ toLower c)]
| otherwise = [letterPresses kb c]
-- guaranteed to be lowercase
letterPresses :: Phone -> Char -> (Key, Presses)
letterPresses kb c = case find (matchSeq c) $ concat $ map charSeqs kb of
-- function is not complete, but this is what exercise signature wants to
Nothing -> error "invalid character"
Just (k, _, n) -> (k, n)
find :: (a -> Bool) -> [a] -> Maybe a
find _ [] = Nothing
find p (x:xs)
| p x = Just x
| otherwise = find p xs
-- matches given character with given keypress sequence,
-- return True if the char in the seq is the same as given char
matchSeq :: Char -> (Key, Char, Presses) -> Bool
matchSeq c (_, c', _) = c == c'
-- all possible tap sequences for a given key, resulting in different characters
-- each tuple is: (k, c, n) where k is key to press, c is character that
-- will result from it and n is a number of presses required
charSeqs :: Key -> [(Key, Char, Presses)]
charSeqs One = []
charSeqs Star = []
charSeqs k@(TextKey digit letters) = zip3 (repeat k) allLetters presses where
allLetters = letters ++ [digit]
presses = [1..(length allLetters)]
-- calculate key sequence to press to print given string
cellPhonesDead :: Phone -> String -> [(Key, Presses)]
cellPhonesDead kb s = concat $ map (reverseTaps kb) s
-- get total number of taps in a sequence
fingerTaps :: [(Key, Presses)] -> Presses
fingerTaps ks = foldr (+) 0 $ map snd ks
-- most frequent letter in a string
mostPopularLetter :: String -> Char
mostPopularLetter "" = error "empty string"
mostPopularLetter s = findMostFrequent s
findMostFrequent :: Ord a => [a] -> a
findMostFrequent [] = error "empty list"
findMostFrequent xs@(x:_) = snd $ foldr max (1, x) freqs where
freq cs = (length cs, head cs)
freqs = map freq $ group $ sort xs
-- most frequent letter in a list of strings
coolestLetter :: [String] -> Char
coolestLetter ss = mostPopularLetter $ concat ss
-- most frequent word in a list of strings
coolestWord :: [String] -> String
coolestWord ss = findMostFrequent totalWords where
totalWords = concat $ map splitWords ss
convo :: [String]
convo =
["Wanna play 20 questions",
"Ya",
"U 1st haha",
"Lol ok. Have u ever tasted alcohol",
"Lol ya",
"Wow ur cool haha. Ur turn",
"Ok. Do u think I am pretty Lol",
"Lol ya",
"Just making sure rofl ur turn"]
Editor is loading...