word_freq.hs en Haskell
Cuenta frecuencias de palabras en un pasaje incrustado e imprime las ocho primeras con totales.
import Data.Char (isAlpha, toLower)
import Data.List (sortOn)
import Data.Map.Strict (Map)
import Data.Ord (Down (..))
import qualified Data.Map.Strict as Map
passage :: String
passage = unwords
[ "The tide goes out and the tide comes in."
, "The boats wait for the tide, and the gulls wait for the boats."
, "Out on the flats the light goes flat and the mud goes silver."
]
-- Lowercase everything, then treat any non-letter as a separator.
normalize :: String -> [String]
normalize = words . map keep
where
keep c
| isAlpha c = toLower c
| otherwise = ' '
-- fromListWith folds the values of duplicate keys together.
tally :: [String] -> Map String Int
tally ws = Map.fromListWith (+) [(w, 1) | w <- ws]
-- Down on the count sorts descending; the word settles ties.
ranked :: Map String Int -> [(String, Int)]
ranked = sortOn (\(w, n) -> (Down n, w)) . Map.toList
pad :: Int -> String -> String
pad n s = s ++ replicate (n - length s) ' '
lpad :: Int -> String -> String
lpad n s = replicate (n - length s) ' ' ++ s
row :: (String, Int) -> String
row (w, n) = pad 10 w ++ lpad 6 (show n)
rule :: String
rule = replicate 16 '-'
main :: IO ()
main = do
let ws = normalize passage
counts = tally ws
putStrLn "word frequency, top 8"
putStrLn (pad 10 "word" ++ lpad 6 "count")
putStrLn rule
mapM_ (putStrLn . row) (take 8 (ranked counts))
putStrLn rule
putStrLn (pad 10 "distinct" ++ lpad 6 (show (Map.size counts)))
putStrLn (pad 10 "total" ++ lpad 6 (show (length ws)))
Cómo funciona
normalizepasa las letras a minúscula y borra todo lo demás antes de quewordsparta el pasaje.tallyarma unMap String IntconMap.fromListWith (+), que pliega juntas las claves repetidas.rankedordena porDown npara que los conteos bajen, yrowarma cada línea comopad 10 w ++ lpad 6 (show n).
Palabras clave y builtins usados aquí
DownIOIntMapStringasdoimportletqualifiedwhere
El intento, en números
- Líneas
- 52
- Caracteres a escribir
- 1477
- Tokens
- 308
- Ritmo de tres estrellas
- 75 tpm
Al ritmo de tres estrellas de 75 tokens por minuto, este intento toma unos 246 segundos.
Paso 1 de 3 en Bis; paso 25 de 27 en Fundamentos del lenguaje.