Advent of Code 2021 day 1

    It's that time again! It's Advent of Code again, and I'm doing it in Haskell again.

    Build environment

    I've been using Stack as a build environment, but it seems all the cool kids have gone back to Cabal again. It took me a while to iron the wrinkles out, the most annoying one was updating the cabal-version directive in the main Cabal file, so that common stanzas could be included. But I got there in the end. We shall see how things go when it comes to profiling and debugging!

    The problem

    We're given a list of depths (2000 numbers). Part A was to find how many numbers that were strictly larger than their predecessor. Part B was to find size-three sliding windows on the input, sum in those windows, and find how many windows summed larger than their predecessor.

    For the "compare against predecessor" I used the trick of zipping a list with its own tail. I went through a few iterations of the "compare to previous" filter, before ending up just using (>) in filter (and uncurry to unpick the tuple from zip):

    main :: IO ()
    main = 
      do  numStrs <- readFile "data/advent01.txt"
          let nums = map (read @Int) $ lines numStrs
          print $ part1 nums
    
    part1 :: [Int] -> Int
    part1 = countIncreasing
    
    countIncreasing :: [Int] -> Int
    countIncreasing nums = length $ filter (uncurry (>)) $ zip (tail nums) nums
    

    For part B, I used tails (from Data.List) to find all the sufixes, take the first three elements of each suffix, then filter to keep only the windows with three items (thus dropping the short few at the end).

    The code is this:

    part2 :: [Int] -> Int
    part2 nums = countIncreasing $ map sum windows
      where windows = filter ((== 3) . length) $ map (take 3) $ tails nums
    

    It's easiest to see how it works by putting the steps into ghci.

    > ns = [1,2,3,4,5,6,7,8]
    > tails ns
     [[1,2,3,4,5,6,7,8],[2,3,4,5,6,7,8],[3,4,5,6,7,8],[4,5,6,7,8],[5,6,7,8],[6,7,8],[7,8],[8],[]]
    
    > map (take 3) $ tails ns
     [[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8],[7,8],[8],[]]
    
    > filter ((==3) . length) $ map (take 3) $ tails ns
     [[1,2,3],[2,3,4],[3,4,5],[4,5,6],[5,6,7],[6,7,8]
    

    Then sum the windows and use the same countIncreasing as before.

    Code

    You can get the code from my locally-hosed Git repo, or from Gitlab.

    Neil Smith

    Read more posts by this author.