Commit 152690da by Stuart Kurtz

Day 9 finished. Finally.

parent afdd349a
Showing with 18 additions and 31 deletions
module Main where
import Data.Array
import Data.List
import Data.Array ( Ix(range, inRange), Array, array, (!), bounds )
import Data.List ( sort )
import qualified Data.Set as S
import Data.Set (Set)
......@@ -36,32 +36,22 @@ lowPoints arr = filter (isLowPoint arr) . range . bounds $ arr
-- This code is wrong for the interpretation of a basin given by
-- the problem.
basin :: Array (Int,Int) Int -> (Int,Int) -> Set (Int,Int)
basin arr pos = search (S.singleton pos) where
frontier :: Set (Int,Int) -> Set (Int,Int)
frontier pts = expansion `S.difference` pts where
expansion = S.fromList . foldr (\pt rest -> neighbors arr pt ++ rest) [] $ pts
search :: S.Set (Int,Int) -> S.Set (Int,Int)
search pts
| not . S.null $ newpoints = search (pts `S.union` newpoints)
| otherwise = pts
where
newpoints = S.fromList
[pt | pt <- S.toList (frontier pts)
, flowPoint pt
, S.fromList (flowsFrom pt) `S.isSubsetOf` pts
]
flowsFrom pt = [p | p <- neighbors arr pt
, arr ! p < arr ! pt]
flowPoint pt = arr ! pt /= 9 && all ((/= arr ! pt) . (arr !)) (neighbors arr pt)
basins :: Array (Int,Int) Int -> [Set (Int,Int)]
basins heightMap = findBasins viablePoints where
viablePoints = S.fromList . filter ((<9) . (heightMap !)) . range . bounds $ heightMap
findBasins s
| S.null s = []
| otherwise =
let foundPoints = searchFrom [S.findMin s] S.empty
in foundPoints : findBasins (s `S.difference` foundPoints)
searchFrom :: [(Int,Int)] -> Set (Int,Int) -> Set (Int,Int)
searchFrom [] visited = visited
searchFrom (p:ps) pts
| p `S.member` pts || heightMap ! p == 9 = searchFrom ps pts
| otherwise = searchFrom (neighbors heightMap p ++ ps) (S.insert p pts)
main :: IO ()
main = do
heightMap <- makeHeightMap <$> readFile "data/heightMap.txt"
putStr . show . take 3 . reverse . sort . map S.size $ basin heightMap <$> lowPoints heightMap
{- failed answers:
414960
-}
\ No newline at end of file
print . product . take 3 . reverse . sort . map S.size . basins $ heightMap
......@@ -45,7 +45,7 @@ paths cm = iter (Small "start") (S.singleton (Small "start")) [Small "start"] wh
iter :: Cave -> Set Cave -> [Cave] -> [[Cave]]
iter (Small "end") _ path = [reverse path]
iter cave visited path = do
next <- filter (`notElem` visited) . (cm !) $ cave
next <- cm ! cave
guard $ next `notElem` visited
case next of
Big _ -> iter next visited (next : path)
......@@ -61,4 +61,3 @@ processCaveFile file = do
main :: IO ()
main = do
processCaveFile "data/caves.txt"
......@@ -65,4 +65,3 @@ processCaveFile file = do
main :: IO ()
main = do
processCaveFile "data/caves.txt"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment