# Advent of Code - 2021 - 12

``````import qualified Data.Set   as Set
import qualified Data.Graph as Graph
import Data.List (sort, group)
import Data.Maybe (fromJust)
import Data.Tuple (swap)

type V = Graph.Vertex
type N = String

parseInput = Graph.graphFromEdges
. group''
. sort
. concat
. sequence [id, map swap]
. map (\x -> let (l,(_:r)) = break (=='-') x in (l, r))
. lines
where
group' :: N -> [N] -> [(N, N)] -> [((), N, [N])]
group' k v [] = [((), k, v)]
group' k v ((k',v'):l) | k == k' = group' k (v':v) l
| k /= k' = ((), k, v) : group' k' [v'] l
group'' :: [(N, N)] -> [((), N, [N])]
group'' ((k, v):l) = group' k [v] l

visit :: (V -> (N, [N])) -> (N -> Maybe V) -> V -> V -> V -> Bool -> Set.Set V -> [[V]]
visit nfv vfk current start end twice visited
= map (current:) \$ foldMap (visitNode) nodes'
where
(curr, nodes) = nfv current
nodes' = map (fromJust . vfk) nodes
visitNode :: V -> [[V]]
visitNode node
| node == end = [[end]]
| Set.member node visited && (twice' || node == start) = []
| otherwise = visit nfv vfk node start end twice' insert
insert | small      = Set.insert current visited
| otherwise  = visited
small = "a" <= curr && curr <= "z"
twice' = twice || Set.member current visited

>>= \x -> let (graph, nodeFromVertex, vertexFromKey) = parseInput x
nfv   = (\((), x, y) -> (x, y)) . nodeFromVertex
vfk   = vertexFromKey
start = fromJust \$ vfk "start"
end   = fromJust \$ vfk "end"
vis   = visit nfv vfk start start end
part1 = vis True  Set.empty
part2 = vis False Set.empty
in  mapM_ print [length part1, length part2]

-- Debugging functions

printPaths nfv = mapM_ (putStrLn . pathToString nfv)

pathToString nfv = tail . foldr ((++) . (',':)) "" . map f
where f = (\(_, l, _) -> l) . nfv``````