Day twelve part one

This commit is contained in:
2024-12-12 20:24:22 +01:00
parent 4e2ef454b5
commit 8d606dd389
9 changed files with 263 additions and 0 deletions

58
day-12-haskell/src/Lib.hs Normal file
View File

@@ -0,0 +1,58 @@
{-# LANGUAGE TupleSections #-}
module Lib (task1) where
import Control.Monad (join)
import Data.List (partition, (!?))
import qualified Data.Set as Set
import Flow
type World = [[Char]]
type Point = (Int, Int)
type Cluster = Set.Set Point
task1 :: String -> IO Int
task1 input = let allClusters = readWorld input |> clusters
in do
return $ sum $ map price allClusters
readWorld :: String -> World
readWorld = lines
clusters :: World -> [Cluster]
clusters world = points |> addToClusters []
where
points :: [Point]
points = zip [0..] world |> map (\(y, line) -> take (length line) [0..] |> map (\x -> (x,y))) |> join
addToClusters :: [Cluster] -> [Point] -> [Cluster]
addToClusters existingClusters [] = existingClusters
addToClusters existingClusters (point:restPoints) =
case partition (\c -> belongingToCluster c point) existingClusters of
([], other) -> addToClusters (Set.singleton point : other) restPoints
(matching, other) -> addToClusters ((map Set.toList matching |> join |> Set.fromList |> Set.insert point) : other) restPoints
belongingToCluster :: Cluster -> Point -> Bool
belongingToCluster cluster point =
let char = inWorld world point
in adjacentPoints point |> filter (\p -> char == inWorld world p) |> any (\x -> Set.member x cluster)
price :: Cluster -> Int
price cluster = length cluster * perimiter cluster
perimiter :: Cluster -> Int
perimiter cluster = Set.toList cluster |> map perimiterOnSquare |> sum
where
perimiterOnSquare :: Point -> Int
perimiterOnSquare position = adjacentPoints position |> filter (\pos -> Set.notMember pos cluster) |> length
inWorld :: World -> Point -> Maybe Char
inWorld world (x,y) = do
line <- world !? y
line !? x
adjacentPoints :: Point -> [Point]
adjacentPoints point = [(-1, 0), (0, -1), (1, 0), (0, 1)] |> map (offset point)
offset :: Num a => (a, a) -> (a, a) -> (a, a)
offset (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)