1 {-# LANGUAGE OverloadedStrings #-}
4 import Data.Function (on)
6 import Data.Text (Text)
7 import qualified Data.Text.IO as TIO
9 import Data.Void (Void)
11 import Text.Megaparsec
12 import Text.Megaparsec.Char
13 import qualified Text.Megaparsec.Char.Lexer as L
14 import qualified Control.Applicative as CA
18 type Flipper = (Int, Flips)
22 flipsT <- TIO.readFile "data/07-flips.txt"
23 let (burgers, flippers) = successfulParse flipsT
24 print $ part1 burgers flippers
25 print $ part2 burgers flippers
28 part1 :: Burgers -> [Flipper] -> Int
29 part1 burgers = length . filter isSorted . map (enflip burgers) . map snd
30 where isSorted items = items == unburntSort items
32 part2 :: Burgers -> [Flipper] -> Int
33 part2 burgers = fst . head . filter isSorted . map (\(n, fs) -> (n, enflip burgers fs))
34 where isSorted (_, items) = (null $ filter (<= 0) items) && (items == sort items)
37 enflip :: Burgers -> Flips -> Burgers
38 enflip = foldl' oneFlip
39 where oneFlip items pos = [-1 * i | i <- (reverse $ take pos items)] ++ (drop pos items)
41 unburntSort :: Burgers -> Burgers
42 unburntSort = sortBy (compare `on` abs)
45 -- Parse the input file
47 type Parser = Parsec Void Text
49 -- don't treat newlines as automatically-consumed whitespace
51 sc = L.space (skipSome (char ' ')) CA.empty CA.empty
54 integer = lexeme L.decimal
57 flipsFileP = (,) <$> burgersP <* newline <*> (flipperP `endBy` newline)
59 burgersP = (:) <$> symb "burgers:" *> many integer
61 flipperP = (,) <$> integer <* symb ":" <*> many integer
63 successfulParse :: Text -> (Burgers, [Flipper])
64 successfulParse input =
65 case parse flipsFileP "input" input of
66 Left _error -> ([], []) -- TIO.putStr $ T.pack $ parseErrorPretty err