I will summarize the problems here, but you should really check out the website to get the full story and to join in!
The puzzle input gives a list of numbers, and we are asked to find the number of times that two consecutive numbers increase for the whole list. My initial thought when asked to compute a single value from a list of values is a fold/reduce. Unfortunately, each step in a fold for this problem would need to keep track of the running total of consecutive increases along with the previous number. A common trick to get this work in Haskell is to first zip the list with its own tail to end up with a list of pairs of consecutive numbers like so. (There are better ways to write this, but you’ll see why I wrote it this way in part two)
list = [199, 200, 208, 210, 200, 207, 240, 269, 260, 263] pairs :: [a] -> [(a, a)] pairs (x:rest) = zip (x:rest) rest
Then we can fold over our list of pairs to calculate the total of consecutive increases:
answer = foldl ( count (a, b) -> if b > a then count + 1 else count ) 0 (pairs list)
[_, answer] = list.reduce( ([previous, count], current) => [ current, current > previous ? count + 1 : count ], [Infinity, 0])
The initial value to the accumulator is a tuple of
Infinity so that the comparison with the first item will always be smaller, and
0 for the start of the count. We use destructuring to pull the answer back out of the tuple at the end.
This part is similar to the first one except we compare consecutive sums of three consecutive numbers. Sounds like we need triples from our list instead of pairs. We can just extend the zip concept with the
triples :: [a] -> [(a, a, a)] triples (x:y:rest) = zip3 (x:y:rest) (y:rest) rest
Then we can map over that to get the sum of each triple. Once we’ve done that, we are back to a list of numbers, so we’ll pair them up again to compare increases in consecutive sums and fold to get the total as before.
answer = foldl ( count (a, b) -> if b > a then count + 1 else count ) 0 (pairs (map ((x, y, z) -> x + y + z ) (triples list)))
There are ways to fix the mess of parentheses, but I won’t get into that for now. The initial strategy of using the tuple to keep track of the previous item and the total kind of falls apart for this part of the problem, so we’ll copy what we did in Haskell.
const zip = (a, b) => Array(Math.min(a.length, b.length)) .fill().map((_,i) => [a[i], b[i]]); const zip3 = (a, b, c) => Array(Math.min(a.length, b.length, c.length)) .fill().map((_,i) => [a[i], b[i], c[i]]); const pairs = ([x, ...rest]) => zip([x, ...rest], rest) const triples = ([x, y, ...rest]) => zip3([x, y, ...rest], [y, ...rest], rest) const answer = pairs( triples(list).map(([x, y, z]) => x + y + z) ).reduce((count, [a, b]) => b > a ? count + 1 : count, 0)
Source: DEV CommunityDecember 2, 2021