Skip to content

Commit c95238c

Browse files
committed
Add day 09 second part
1 parent 395aec9 commit c95238c

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

09/src/main.hs

+45-13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import Data.Char (digitToInt)
2+
import Data.List (find)
3+
import Data.Maybe
24

35
enumerate :: [a] -> [(Int, a)]
46
enumerate = zip [0 ..]
@@ -7,32 +9,62 @@ linesToHeightmap :: [String] -> [[Int]]
79
linesToHeightmap = map (map digitToInt)
810

911
isOutOfBounds :: [[Int]] -> (Int, Int) -> Bool
10-
isOutOfBounds matrix (x, y) = x < 0 || y < 0 || x >= maxX || y >= maxY
11-
where
12-
maxX = length matrix
13-
maxY = length (head matrix)
12+
isOutOfBounds matrix (x, y) = x < 0 || y < 0 || x >= length matrix || y >= length (matrix !! x)
1413

15-
findSurrounding :: [[Int]] -> (Int, Int) -> [Int]
14+
findSurrounding :: [[Int]] -> (Int, Int) -> [Maybe Int]
1615
findSurrounding matrix (x, y) = map (getElementAt matrix) positions
1716
where
1817
positions = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
1918

20-
getElementAt :: [[Int]] -> (Int, Int) -> Int
21-
getElementAt matrix point@(x, y) = if isOutOfBounds matrix point then -1 else (matrix !! y) !! x
19+
getElementAt :: [[Int]] -> (Int, Int) -> Maybe Int
20+
getElementAt matrix point@(x, y) = if isOutOfBounds matrix point then Nothing else Just ((matrix !! x) !! y)
2221

23-
isPointLowest :: Int -> [Int] -> Bool
24-
isPointLowest x = all (> x)
22+
isPointLowest :: Int -> [Maybe Int] -> Bool
23+
isPointLowest x = all f
24+
where
25+
f (Just n) = n > x
26+
f Nothing = True
2527

2628
getLowPoints :: [[Int]] -> [Int]
27-
getLowPoints matrix = foldl (\acc (x, row) -> acc ++ getLowPointsFromRow x row) [] (enumerate matrix)
29+
getLowPoints matrix =
30+
foldl (\acc (x, row) -> acc ++ getLowPointsFromRow x row) [] (enumerate matrix)
31+
where
32+
getLowPointsFromRow xa row =
33+
map snd (filter (\(ya, point) -> isPointLowest point (findSurrounding matrix (xa, ya))) (enumerate row))
34+
35+
floodFill :: [[Int]] -> (Int, Int) -> [(Int, Int)] -> Int
36+
floodFill matrix point@(x, y) visited =
37+
if value < 9 && notVisited then 1 + foldl (\acc p -> acc + floodFill matrix p (point : visited)) 0 positions else 0
38+
where
39+
value =
40+
case getElementAt matrix point of
41+
Nothing -> 9
42+
(Just z) -> z
43+
positions = [(x - 1, y), (x + 1, y), (x, y - 1), (x, y + 1)]
44+
notVisited = isNothing (find (== point) visited)
45+
46+
replaceMaxBasin :: (Int, Int, Int) -> Int -> (Int, Int, Int)
47+
replaceMaxBasin allb@(b1, b2, b3) bn
48+
| b1 < bn = (bn, b2, b3)
49+
| b2 < bn = (b1, bn, b3)
50+
| b3 < bn = (b1, b2, bn)
51+
| otherwise = allb
52+
53+
getLargestBasins :: [[Int]] -> (Int, Int, Int)
54+
getLargestBasins matrix =
55+
foldl (\acc (x, row) -> foldl replaceMaxBasin acc (getBasins x row)) (0, 0, 0) (enumerate matrix)
2856
where
29-
getLowPointsFromRow xa row = map snd (filter (\(ya, point) -> isPointLowest point (findSurrounding matrix (xa, ya))) (enumerate row))
57+
getBasins xa row =
58+
map (\(ya, point) -> if isPointLowest point (findSurrounding matrix (xa, ya)) then floodFill matrix (xa, ya) [] else 0) (enumerate row)
3059

3160
sumLowPoints :: [Int] -> Int
3261
sumLowPoints = foldl (\acc c -> acc + c + 1) 0
3362

3463
main :: IO ()
3564
main = do
36-
input <- readFile "input.txt"
65+
input <- readFile "test.txt"
3766
let heightmap = (linesToHeightmap . lines) input
38-
print $ getLowPoints heightmap
67+
let (b1, b2, b3) = getLargestBasins heightmap
68+
print (b1, b2, b3)
69+
print (b1 * b2 * b3)
70+
print $ sumLowPoints $ getLowPoints heightmap

09/test.txt

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2199943210
2+
3987894921
3+
9856789892
4+
8767896789
5+
9899965678

0 commit comments

Comments
 (0)