-
Here's my haskell part 2. I noticed you had a comment where you had an issue using
foldr
, but things work withfoldl
. The reason for this is thatfoldr
is for a right-associative operator. But the operator as defined in the problem (for part 2) is left associative (if you think about this, it's because you're starting at the beginning of the list and updating the depth based on the current aim). So you can either dofoldr op ... (reverse instructions)
orfoldl op ... instructions
. If you're then doingfoldl
, it's better to usefoldl'
(fromData.Foldable
) as you're more efficient since you collapse as you go, rather than consing all the computation at once. Sincefoldl
doesn't work on infinite lists anyway, this is always safe to do.module Main where import Data.Foldable (foldl') data Move = F Int | D Int deriving (Eq, Show) parse :: String -> Maybe Move parse ('f':xs) = Just . F $ read (drop 7 xs) parse ('d':xs) = Just . D $ read (drop 4 xs) parse ('u':xs) = Just . D $ -read (drop 2 xs) parse _ = Nothing inp :: String -> IO (Maybe [Move]) inp path = do c <- readFile path return $ mapM parse (lines c) part1 :: Maybe [Move] -> Int part1 Nothing = 0 part1 (Just xs) = h * d where (h, d) = foldl' (\(h, d) x -> case x of F n -> (h + n, d) D n -> (h, d + n)) (0, 0) xs part2 :: Maybe [Move] -> Int part2 Nothing = 0 part2 (Just xs) = h * d where (h, d, _) = foldl' (\(h, d, a) x -> case x of F n -> (h + n, d + (a * n), a) D n -> (h, d, a + n)) (0, 0, 0) xs main :: IO () main = do instructions <- inp "../inputs/2021/day02.input" print $ part1 instructions print $ part2 instructions
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):FWIW, an idiomatic way of chunking a list would be:
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 listtails [1, 2, 3, 4] = [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4], []]
. So if wetake n
we will get the right inputs for zipping together to produce a window of length n. We can't usezip
though, because that needs two lists. Sofoldr (zipWith (:)) (repeat [])
is generalisingzip
ton
inputs and producing a list of lists as outputs (rather than a list of tuples)...