Advent of Code 2024 day 25

    After the struggle of day 24, the final day 25 puzzle was a gentle relief.

    A Schematic is either a Lock or a Key. Both have a list of heights.

    data Schematic = Lock [Int] | Key [Int]
      deriving (Show, Eq, Ord)

    I read the input by splitting it into lines, splitting it into schematics on blank lines, making the schematics, then splitting into locks and keys.

    makeSchematics :: String -> ([Schematic], [Schematic])
    makeSchematics = partition isLock . fmap makeSchematic . splitOn [""] . lines
      where isLock (Lock _) = True
            isLock _ = False
    
    makeSchematic :: [String] -> Schematic
    makeSchematic ss
      | isKeySchematic ss = Key $ heightsOf ss
      | isLockSchematic ss = Lock $ heightsOf ss
      | otherwise = error "Invalid schematic"
    
    isKeySchematic, isLockSchematic :: [String] -> Bool
    isKeySchematic  [a,_,_,_,_,_,b] = a == "....." && b == "#####"
    isLockSchematic [a,_,_,_,_,_,b] = a == "#####" && b == "....."
    
    heightsOf :: [String] -> [Int]
    heightsOf = fmap ((-1 +) . length . filter (== '#')) . transpose

    That converts the input into the list-of-heights form given in the puzzle description.

    A lock and key are compatible if all the matching heights sum to less than or equal to five. A list comprehension finds all possible pairs of lock and key, filtered by compatibility.

    part1 :: [Schematic] -> [Schematic] -> Int
    part1 locks keys = length [(l, k) | l <- locks, k <- keys, compatible l k]
    
    compatible :: Schematic -> Schematic -> Bool
    compatible (Lock ls) (Key ks) = all (<= 5) $ zipWith (+) ls ks

    And that's the end of the Advent of Code for another year!

    500 stars

    Code

    You can get the code from my locally-hosted Git repo, or from Codeberg.

    Neil Smith

    Read more posts by this author.