OK. I will start with an “.exs” file and declare a module to solve the problem. I’ll go ahead and put the data points into a module attribute and we’ll declare a function `solve_problem()`

that we hope will solve the exercise (but for now we’ll just inspect the list).

```
defmodule Solution do
@data_points [
["2018-12-01", "AM", "ID123", 5000],
["2018-12-01", "AM", "ID545", 7000],
["2018-12-01", "PM", "ID545", 3000],
["2018-12-02", "AM", "ID545", 7000]
]
def solve_problem do
@data_points
end
end
IO.inspect(Solution.solve_problem())
```

First we want to separate the data points out and group them by date. We can use the `Enum.group_by`

function to accomplish that to group the list of lists. The element we want to group by is the first item in the list so I’ll go ahead and use the `List.first`

function to get at it. `group_by`

can also transform the result so let’s drop the date from the collected data points:

```
def data_points_by_date(data_points) do
Enum.group_by(data_points, &List.first/1, &Enum.drop(&1, 1))
end
```

The result of passing the data points to that function is:

```
%{
"2018-12-01" => [
["AM", "ID123", 5000],
["AM", "ID545", 7000],
["PM", "ID545", 3000]
],
"2018-12-02" => [["AM", "ID545", 7000]]
}
```

A map is a collection of key-value pairs. In this case the key is the date and the value is a list of data points. We want to group the data points in each value by their “meridians” (AM or PM). We can repeat the same use of `Enum.group_by`

and `List.first`

again on the values. In our `group_by`

transform we might also collect the numbers from the list. Let’s do that with pattern matching on the lists of three values.

```
…
def group_by_meridian({date, data_points}) do
{date, Enum.group_by(data_points, &List.first/1, fn [_, _, number] -> number end}
end
def solve_problem do
@data_points
|> data_points_by_date()
|> Enum.into(%{}, &group_by_meridian/1)
end
```

yields:

```
%{
"2018-12-01" => %{"AM" => [5000, 7000], "PM" => [3000]},
"2018-12-02" => %{"AM" => [7000]}
}
```

And we’re pretty close. We just need to sum up the values in the lists of numbers instead of returning the lists themselves. We can change `group_by_meridian`

to do that using techniques we’ve already seen. We can build the map of meridians by pulling the expression out into a variable:

```
def group_by_meridian({date, data_points}) do
numbers_by_meridian = Enum.group_by(data_points, &List.first/1, fn([_, _, number]) -> number end)
{date, numbers_by_meridian}
end
```

(so `numbers_by_meridian`

will look something like `%{"AM" => [5000, 7000], "PM" => [3000]`

)

Now we can use the trick of doing a `Enum.map`

over the key value pairs in `numbers_by_meridian`

where we change the list of numbers into sums. (I actually use `Enum.into`

again which does the `Enum.map`

under the covers). To calculate the sums we use `Enum.reduce`

and pass in the binary function “+” (or `Kernel.+`

). The function looks like this at first blush:

```
def group_by_meridian({date, data_points}) do
numbers_by_meridian = Enum.group_by(data_points, &List.first/1, fn([_, _, number]) -> number end)
sums_by_meridian = Enum.into(numbers_by_meridian, %{}, fn {meridian, numbers} -> {meridian, Enum.reduce(numbers, 0, &+/2)} end)
{date, sums_by_meridian}
end
```

And we can clean up things a bit:

```
defmodule Solution do
@data_points [
["2018-12-01", "AM", "ID123", 5000],
["2018-12-01", "AM", "ID545", 7000],
["2018-12-01", "PM", "ID545", 3000],
["2018-12-02", "AM", "ID545", 7000]
]
# Take the data points and create a map grouping them by date
def data_points_by_date(data_points) do
Enum.group_by(data_points, &List.first/1, &Enum.drop(&1,1))
end
def group_by_meridian({date, data_points}) do
sums_by_meridian = data_points
|> Enum.group_by(&List.first/1, &extract_number/1)
|> Enum.into(%{}, &sum_numbers/1)
{date, sums_by_meridian}
end
def solve_problem do
@data_points
|> data_points_by_date()
|> Enum.into(%{}, &group_by_meridian/1)
end
defp extract_number([_, _, number]), do: number
defp sum_numbers({meridian, numbers_list}), do: {meridian, Enum.reduce(numbers_list, &+/2)}
end
IO.inspect(Solution.solve_problem())
```

yielding:

```
%{
"2018-12-01" => %{"AM" => 12000, "PM" => 3000},
"2018-12-02" => %{"AM" => 7000}
}
```