typestar

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

  1. normalize pasa las letras a minúscula y borra todo lo demás antes de que words parta el pasaje.
  2. tally arma un Map String Int con Map.fromListWith (+), que pliega juntas las claves repetidas.
  3. ranked ordena por Down n para que los conteos bajen, y row arma cada línea como pad 10 w ++ lpad 6 (show n).

Palabras clave y builtins usados aquí

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.

Escribe este fragmento

Paso 1 de 3 en Bis; paso 25 de 27 en Fundamentos del lenguaje.

← Anterior Siguiente →