1
1
import Data.Char (isLower )
2
+ import Data.List (nub )
2
3
import Data.List.Split (splitOn )
3
4
import Data.Map as M (Map , empty , insertWith , (!) )
4
5
@@ -14,6 +15,8 @@ main = do
14
15
input <- readInput " day12/input"
15
16
print $ " Test input: " ++ show (firstProblem testInput) ++ " == 10"
16
17
print $ " Problem input: " ++ show (firstProblem input) ++ " == 3738"
18
+ print $ " Test input: " ++ show (secondProblem testInput) ++ " == 36"
19
+ print $ " Problem input: " ++ show (secondProblem input) ++ " == 120506"
17
20
where
18
21
readInput file = foldl foldLine M. empty . lines <$> readFile file
19
22
foldLine acc = insertNew acc . splitOn " -"
@@ -28,16 +31,32 @@ isSmall = isLower . head
28
31
29
32
type CaveConections = Map Cave [Cave ]
30
33
34
+ type Path = [Cave ]
35
+
31
36
firstProblem :: CaveConections -> Int
32
- firstProblem = length . getPaths
37
+ firstProblem = problem caveFilter
38
+ where
39
+ caveFilter path cave = not $ isSmall cave && elem cave path
40
+
41
+ secondProblem :: CaveConections -> Int
42
+ secondProblem = problem caveFilter
43
+ where
44
+ caveFilter path cave =
45
+ let visitedSmallTwice = (\ a -> length (nub a) /= length a) $ filter isSmall path
46
+ in if visitedSmallTwice
47
+ then not $ isSmall cave && elem cave path
48
+ else cave /= " start"
49
+
50
+ problem :: (Path -> Cave -> Bool ) -> CaveConections -> Int
51
+ problem predicate = length . getPaths predicate
33
52
34
- getPaths :: CaveConections -> [[ String ] ]
35
- getPaths connections = getPaths' [" start" ]
53
+ getPaths :: ( Path -> Cave -> Bool ) -> CaveConections -> [Path ]
54
+ getPaths predicate connections = getPaths' [" start" ]
36
55
where
37
56
getPaths' path@ (" end" : _) = [reverse path]
38
57
getPaths' path =
39
- let possibleMovements = filterSmall path $ connections ! head path
58
+ let possibleMovements = filterByPredicate path $ connections ! head path
40
59
in if null possibleMovements
41
60
then []
42
61
else concatMap (getPaths' . (: path)) possibleMovements
43
- filterSmall path = filter $ not . ( \ cave -> isSmall cave && elem cave path)
62
+ filterByPredicate path = filter $ predicate path
0 commit comments