This repository has been archived by the owner on Jun 25, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
/
sort.hs
51 lines (46 loc) · 1.82 KB
/
sort.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
{-# LANGUAGE TupleSections #-}
import Control.Arrow (Arrow ((***)))
import Control.Monad (unless)
import Data.Char (toLower)
import Data.List (isPrefixOf)
import Data.Map (Map)
import qualified Data.Map as M
import System.Exit (die)
import Text.ParserCombinators.Parsec
-- | Parse a project name until the first right square bracket
projectName :: Parser String
projectName = many1 (noneOf "]")
-- | Parse a list item
parseItem :: Parser String
parseItem = do
char '-' <* spaces
map toLower . dropWhile (== '#') <$> choice parsers
where
-- All ways to parse a project name, cited or not.
parsers :: [Parser String]
parsers = [cited, id] <*> [projectName]
cited :: Parser a -> Parser a
cited = between (char '[') (char ']')
-- | Build a frequency table from a list
freqs :: Ord a => [a] -> Map a Int
freqs = M.fromListWith (+) . map (,1)
main :: IO ()
main = do
f <- lines <$> readFile "README.md"
let (Right a, Right b) = (g *** g) (break ("##" `isPrefixOf`) f)
g = traverse (parse parseItem "") . filter ("-" `isPrefixOf`)
(ma, mb) = (freqs a, freqs b)
-- as and bs are sorted since M.keys returns them in ascending order
(as, bs) = (M.keys ma, M.keys mb)
(dupsa, dupsb) = (M.filter (/= 1) ma, M.filter (/= 1) mb)
-- Check duplication
unless (M.null dupsa) (die $ "The following channels are duplicated in the leave list: " ++ show dupsa)
unless (M.null dupsb) (die $ "The following channels are duplicated in the stay list: " ++ show dupsb)
-- Write lists to files (to be checked with git diff later)
writeFile "a.txt" (unlines a)
writeFile "a-sorted.txt" (unlines as)
writeFile "b.txt" (unlines b)
writeFile "b-sorted.txt" (unlines bs)
-- Report statistics
putStrLn $ "Channels in leave list: " ++ show (M.size ma)
putStrLn $ "Channels in stay list: " ++ show (M.size mb)