Alternative, using an interval library
[advent-of-code-22.git] / advent04 / Main-interval.hs
1 -- Writeup at https://work.njae.me.uk/2022/12/04/advent-of-code-2022-day-4/
2
3 import System.Environment
4 import Data.Text (Text)
5 import qualified Data.Text.IO as TIO
6 import Data.Attoparsec.Text hiding (Result)
7 import Numeric.Interval hiding (null)
8 -- import Control.Applicative
9
10 type Assignment = Interval Int
11 type Pair = (Assignment, Assignment)
12
13 main :: IO ()
14 main =
15 do dataFileName <- getDataFileName
16 text <- TIO.readFile dataFileName
17 let pairs = successfulParse text
18 print $ part1 pairs
19 print $ part2 pairs
20
21 getDataFileName :: IO String
22 getDataFileName =
23 do args <- getArgs
24 progName <- getProgName
25 let baseDataName = if null args
26 then progName
27 else head args
28 let dataFileName = "data/" ++ baseDataName ++ ".txt"
29 return dataFileName
30
31 part1 :: [Pair] -> Int
32 part1 = length . (filter hasContainment)
33
34 part2 :: [Pair] -> Int
35 part2 = length . (filter $ uncurry (==?))
36
37 hasContainment :: Pair -> Bool
38 hasContainment (assignment1, assignment2) =
39 (assignment1 `contains` assignment2) || (assignment2 `contains` assignment1)
40
41
42 -- Parse the input file
43
44 pairsP :: Parser [Pair]
45 pairP :: Parser Pair
46 assignmentP :: Parser Assignment
47
48 pairsP = pairP `sepBy` endOfLine
49 pairP = (,) <$> assignmentP <* "," <*> assignmentP
50
51 assignmentP = (...) <$> decimal <* "-" <*> decimal
52
53 successfulParse :: Text -> [Pair]
54 successfulParse input =
55 case parseOnly pairsP input of
56 Left _err -> [] -- TIO.putStr $ T.pack $ parseErrorPretty err
57 Right pairs -> pairs