43 lines
1.4 KiB
Haskell
43 lines
1.4 KiB
Haskell
module Day12 where
|
|
import Data.Map ( Map, fromList, unionWith, empty, (!) )
|
|
import Data.List.Split (splitOn)
|
|
import qualified Data.Char
|
|
|
|
type Path = (String,String)
|
|
type System = Map String [String]
|
|
|
|
readPath :: String -> Path
|
|
readPath s = (from,to) where [from,to] = splitOn "-" s
|
|
|
|
addPath :: Path -> System -> System
|
|
addPath (from,to) = unionWith (++) (Data.Map.fromList [(from,[to]), (to,[from])])
|
|
|
|
isLower :: String -> Bool
|
|
isLower = Data.Char.isLower . head
|
|
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)
|
|
|
|
pathFinder2 :: System -> [String] -> [[String]]
|
|
pathFinder2 sys p@("end":xs) = [p]
|
|
pathFinder2 sys p@(x:xs) = concatMap (\next -> f next sys (next:p)) elig
|
|
where
|
|
f cave = if isUpper cave || cave `notElem` p then pathFinder2 else pathFinder
|
|
elig = filter (/= "start") (sys ! x)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- map readPath . lines <$> getContents
|
|
let system = foldr addPath Data.Map.empty input
|
|
|
|
putStrLn "part 1: "
|
|
let paths = map reverse $ pathFinder system ["start"]
|
|
print $ length paths
|
|
|
|
putStrLn "part 2: "
|
|
let paths = map reverse $ pathFinder2 system ["start"]
|
|
print $ length paths |