# Untitled

unknown
3 years ago
3.2 kB
2
Indexable
Never
```module Ch11.Phone where
import Data.Char (toLower, isUpper)
import Data.List (group, sort)

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"]
```