Mucking around with task 5
[summerofcode2018soln.git] / src / task5 / task5.hs
1 {-# LANGUAGE OverloadedStrings #-}
2
3 import Data.Text (Text)
4 import qualified Data.Text as T
5 import qualified Data.Text.IO as TIO
6 import Data.Char (isSpace)
7
8
9 main :: IO ()
10 main = do
11 text <- TIO.readFile "data/05-instructions.txt"
12 let uncommented = deComment text
13 let expanded = expand uncommented
14 print $ countNonSpace uncommented
15 print $ countNonSpace expanded
16 -- TIO.writeFile "data/05-output.ppm" expanded
17
18
19 countNonSpace :: Text -> Int
20 countNonSpace = T.length . T.filter (\c -> not (isSpace c))
21
22
23 -- Remove comments
24 deComment :: Text -> Text
25 deComment text = deComment' (extractFirstComment text) text
26
27 -- If there are no comments, return the text as-is
28 -- If there is a first comment, decomment the rest
29 deComment' :: Maybe (Text, Text) -> Text -> Text
30 deComment' Nothing text = text
31 deComment' (Just (prefix, suffix)) _ = prefix `T.append` (deComment suffix)
32
33 -- Monad notation to string togeether all the Maybes
34 extractFirstComment :: Text -> Maybe (Text, Text)
35 extractFirstComment text =
36 do (prefix, commentSuffix) <- maybeBreakOn "<" text
37 (_, suffix) <- maybeBreakOn ">" commentSuffix
38 return (prefix, suffix)
39
40
41 -- Expand compression
42 expand :: Text -> Text
43 expand text = expand' (extractFirstExpander text) text
44
45 -- If there are no compression markers, return the text
46 -- If there's one, expand it, and try again.
47 expand' :: Maybe (Text, Int, Int, Text) -> Text -> Text
48 expand' Nothing text = text
49 expand' (Just (prefix, expandLen, expandCount, suffix)) _ =
50 expand (expandedPrefix `T.append` suffix)
51 where unexpandedPrefix = T.dropEnd expandLen prefix
52 group = T.takeEnd expandLen prefix
53 expanded = T.replicate expandCount group
54 expandedPrefix = unexpandedPrefix `T.append` expanded
55
56 extractFirstExpander :: Text -> Maybe (Text, Int, Int, Text)
57 extractFirstExpander text =
58 do (prefix, suffix) <- maybeBreakOn ":" text
59 (expanderLenT, suffix') <- maybeBreakOn ":" suffix
60 (expanderCountT, suffix'') <- maybeBreakOn ":" suffix'
61 let expanderLen = read $ T.unpack expanderLenT
62 let expanderCount = read $ T.unpack expanderCountT
63 return (prefix, expanderLen, expanderCount, suffix'')
64
65
66 -- Uses Text.breakOn, but puts the result in a Maybe
67 -- Also drops the needle from the returned suffix.
68 maybeBreakOn :: Text -> Text -> Maybe (Text, Text)
69 maybeBreakOn needle haystack =
70 if T.null suffix
71 then Nothing
72 else Just (prefix, T.drop (T.length needle) suffix)
73 where (prefix, suffix) = T.breakOn needle haystack