Last active
December 12, 2021 10:52
-
-
Save joncol/631feffd813a4c21fa292ca5c960032b to your computer and use it in GitHub Desktop.
AoC 2021, day 12
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Day12 where | |
import Control.Applicative (Alternative((<|>))) | |
import Data.List ((\\)) | |
import Data.Maybe (isJust) | |
import Data.Text (Text) | |
import GHC.Generics (Generic) | |
import Optics | |
import Text.Megaparsec (some) | |
import Text.Megaparsec.Char (char, eol, lowerChar, upperChar) | |
import qualified Data.Text as T | |
import qualified Data.Text.IO as TIO | |
import Parser ( parse, Parser ) | |
data Cave = BigCave Text | SmallCave Text deriving (Eq, Ord, Show, Generic) | |
type Edge = (Cave, Cave) | |
type Path = [Cave] | |
part1 :: FilePath -> IO Int | |
part1 filename = solver filename nf | |
where | |
nf :: Path -> Bool -> [Cave] -> [Cave] | |
nf path _ ns = ns \\ filter (isJust . preview #_SmallCave) path | |
part2 :: FilePath -> IO Int | |
part2 filename = solver filename nf | |
where nf path flag ns | flag = ns \\ filter (isJust . preview #_SmallCave) path | |
| otherwise = ns \\ [SmallCave "start"] | |
solver :: FilePath -> (Path -> Bool -> [Cave] -> [Cave]) -> IO Int | |
solver filename nf = do | |
edges <- parse (some parseEdge) =<< TIO.readFile filename | |
pure . length $ findPaths edges (SmallCave "start") [] False nf | |
parseEdge :: Parser Edge | |
parseEdge = (,) <$> (cave <* char '-') <*> (cave <* eol) | |
where cave = (SmallCave . T.pack <$> some lowerChar) <|> (BigCave . T.pack <$> some upperChar) | |
findPaths :: [Edge] -> Cave -> Path -> Bool -> (Path -> Bool -> [Cave] -> [Cave]) -> [Path] | |
findPaths edges cave path flag nf | |
| cave == SmallCave "end" = [path'] | |
| otherwise = foldMap (\n -> findPaths edges n path' flag' nf) ns' | |
where | |
path' = cave : path | |
flag' = flag || isJust (cave ^? #_SmallCave) && cave `elem` path | |
ns' = nf path flag' (neighbors edges cave) | |
neighbors :: Eq a => [(a, a)] -> a -> [a] | |
neighbors edges vertex = [ v2 | (v1, v2) <- edges, vertex == v1 ] ++ [ v1 | (v1, v2) <- edges, vertex == v2 ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment