You are reading a single comment by @wence and its replies. Click here to read the full conversation.
  • For day 1, there's quite an elegant solution using zipWith. Note that you don't actually have to chunk things up, as pointed out, since the windows overlap you only ever have to care about the start and end points (which can be achieved by zipping together the input list and the input list offset by the window length):

    module Main where
    
    inp :: String -> IO [Int]
    inp path = do
      c <- readFile path
      return $ map read (lines c)
    
    solve :: Int -> [Int] -> Int
    solve n xs = length . filter id $ zipWith (<) xs (drop n xs)
    
    main :: IO ()
    main = do
      vals <- inp "day01.input"
      print $ solve 1 vals
      print $ solve 3 vals
    

    FWIW, an idiomatic way of chunking a list would be:

    import Data.List (tails)
    
    chunk :: Int -> [a] -> [[a]]
    chunk n xs = foldr (zipWith (:)) (repeat []) (take n (tails xs))
    

    Why does this work? Suppose you have two lists [1, 2, 3, 4] and [2, 3, 4]. If you zip them together you get [(1, 2), (2, 3), (3, 4)] which is chunking by two. tails produces all tails of a list tails [1, 2, 3, 4] = [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4], []]. So if we take n we will get the right inputs for zipping together to produce a window of length n. We can't use zip though, because that needs two lists. So foldr (zipWith (:)) (repeat []) is generalising zip to n inputs and producing a list of lists as outputs (rather than a list of tuples)...

About

Avatar for wence @wence started