diff --git a/2021/day12.hs b/2021/day12.hs index c605f1e..46f20f6 100644 --- a/2021/day12.hs +++ b/2021/day12.hs @@ -1,4 +1,5 @@ module Day12 where +import Data.HashSet (HashSet, member, insert, fromList) import Data.Map ( Map, fromList, unionWith, empty, (!) ) import Data.List.Split (splitOn) import qualified Data.Char @@ -15,16 +16,18 @@ addPath (from,to) = unionWith (++) (Data.Map.fromList [(from,[to]), (to,[from])] isUpper :: String -> Bool isUpper = Data.Char.isUpper . head -pathFinder :: System -> [String] -> [[String]] -pathFinder sys p@("end":xs) = [p] -pathFinder sys p@(x:xs) = concatMap (\next -> pathFinder sys (next:p)) elig - where elig = filter (\cave -> isUpper cave || cave `notElem` p) (sys ! x) +pathFinder :: System -> [String] -> HashSet String -> [[String]] +pathFinder _ [] _ = error "no starting point!" +pathFinder sys p@("end":xs) _ = [p] +pathFinder sys p@(x:xs) visited = concatMap (\next -> pathFinder sys (next:p) (next `insert` visited)) elig + where elig = filter (\cave -> isUpper cave || not (cave `member` visited)) (sys ! x) -pathFinder2 :: System -> [String] -> [[String]] -pathFinder2 sys p@("end":xs) = [p] -pathFinder2 sys p@(x:xs) = concatMap (\next -> f next sys (next:p)) elig +pathFinder2 :: System -> [String] -> HashSet String -> [[String]] +pathFinder2 _ [] _ = error "no starting point!" +pathFinder2 sys p@("end":xs) _ = [p] +pathFinder2 sys p@(x:xs) visited = concatMap (\next -> f next sys (next:p) (next `insert` visited)) elig where - f cave = if isUpper cave || cave `notElem` p then pathFinder2 else pathFinder + f cave = if isUpper cave || not (cave `member` visited) then pathFinder2 else pathFinder elig = filter (/= "start") (sys ! x) main :: IO () @@ -33,9 +36,9 @@ main = do let system = foldr addPath Data.Map.empty input putStrLn "part 1: " - let paths = map reverse $ pathFinder system ["start"] + let paths = map reverse $ pathFinder system ["start"] (Data.HashSet.fromList ["start"]) print $ length paths putStrLn "part 2: " - let paths = map reverse $ pathFinder2 system ["start"] + let paths = map reverse $ pathFinder2 system ["start"] (Data.HashSet.fromList ["start"]) print $ length paths