# How to extract multiple elements from a list and do something with them?

Hello,
parallel to Exercism i use Hackerrank to practice at work.
At this i am really struggeling with the 2D Array data structures challange. The following code should solve the problem, but unfortunately does not compile.

``````hourglassSum arr = do
sumAndMax unpack2DArray arr

unpack2DArray [] = []
unpack2DArray (head : tail) =
append1DArray (head (unpack2DArray tail))

append1DArray (head : []) tail2 =
append1DArray (head : tail) tail2 =
append1DArray tail tail2

sumAndMax arr
case arr of
(a:b:c:_:_:_:_:d:_:_:_:_:e:f:g:[]) -> a+b+c+d+e+f+g
(a:b:c:_:_:_:_:d:_:_:_:_:e:f:g:_) ->
let prev = sumAndMax (Data.List.tail (arr))
let cur = a+b+c+d+e+f+g
if cur > prev then
cur
else
prev
``````

If i were to use pattern matching in the function signature of “sumAndMax”, i do not know how to take the whole list and pass it on for recursion. Therefore, i want to extract the data later, sum it and then call the recursion. How can i achieve this?

The posted code has some syntax issues:

``````-sumAndMax arr
+sumAndMax arr =
``````
``````-            let prev = sumAndMax (Data.List.tail (arr))
+            let prev = sumAndMax (Data.List.tail (arr)) in
-            let cur = a+b+c+d+e+f+g
+            let cur = a+b+c+d+e+f+g in
``````

There are also some type errors, some with obvious fixes and some with less obvious ones. I recommend always giving type signatures for global definitions and non-trivial local definitions, because they greatly help finding logic errors.

The HackerRank problem is about a 2D structure. I do not know off the top of my head how to solve it with a flat list (if that is even – reasonably – possible). A complicating factor is that the array is not guaranteed to be a certain size. You probably want to use a `[[Int]]` or an `Array (Int, Int) Int` instead. Indexing can be done with `!!` (list, partial), `!?` (list, total), and `!` (array, partial).

The first solution that comes to my mind goes

(code provided in an attempt to communicate approach to problems generally)

``````maxHourglassSum array = maximum hourglassSums
where
hourglassSums :: [Int]
hourglassSums = map sum hourglasses

hourglasses :: [[Int]]
hourglasses = map hourglassAt coordinates

coordinates = _  -- where are all the hourglasses?
hourglassAt coordinate = _  -- an indexing feast
``````

I’m not seeing what to recurse on here, sorry. Are there ways of combining subsolutions into larger solutions?

In the problem specification of the 2d Array it is guaranteed that the input is 6 by 6.
The input is a list of lists. Because the recursive natrue of lists in Haskell is new to me, i try to use it as much as possible. With indexing, i could probably solve the problem within a blink of an eye.

The recursion should lie in the sumAndMax function. If the input array is large enough, call the same function with the tail of the array, until the array has reached a certain length. Basically, by omitting the head in the next recursion, i shift the indices by one to the right. If the sum is greater then the previous one, use this sum, else use the previous.

What does the in Keyword do? The Haskell Wiki article about keywords does not really help: Keywords - HaskellWiki. I also did not encurter it in any Haskell book so far.

Ah, I missed that.

Assuming that the array be represented as a `[[Int]]`, this might look like

``````sumAndMax (firstRow : secondRow : thirdRow : rest) =
maxHourglassSumInRows firstRow secondRow thirdRow
`max`
sumAndMax (secondRow : thirdRow : rest)  -- recursion
sumAndMax _ = minBound  -- base cases
``````

Does that help?

I still haven’t been able to come up with a flat list approach.

Just like `then` and `else`, `in` never comes alone: it is part of the `let … in _` expression.

`let` expressions are similar in purpose to `where` clauses. The differences are

• `let` expressions are expressions, so you can do whatever with them:
``````_ = 3 * (let x = 5 in x + x) `div` 2
``````
You cannot do anything like this with `where` clauses, which are stuck to declarations and `case` expressions.
• `let` expressions list the local definitions before the main expression, whereas `where` clauses list them after.

`let`’s and `where`’s purposes are the same: allowing local definitions.

Inside `do` blocks `let` does occur alone, but that is syntactic sugar for `let … in _`:

``````_ = do
actions
let value = computation
moreActions value
-- which means
_ = actions >> let value = computation in moreActions value
``````

The `let _ = _` that is sometimes seen in GHCi contexts (example in LYAH) is actually the one from `do` notation. GHCi is special like that. A REPL in an language without true variables is a bit weird.