Pattern Matching question related to sum of pairs from Dave Thomas' Elixir for Programmers course

Greetings for the day! Of late, I’ve been doing the Elixir for Programmers course by Dave Thomas and
one of the sections of the course is about Pattern Matching and there’s a particular subsection of that course called “Lists and Recursion” that exposes one to different ways they could use pattern matching in the context of lists.

One of the pattern matching exercises is given a list calculate the sum_pairs. So let’s say your list is: [ 1, 2, 3, 4, 5, 6 ], Lists.sum_pairs( [ 1, 2, 3, 4, 5, 6 ]) should give you: [3, 7, 11]

There’s a particular part of this section which is mostly like a Do it yourself type thing and one of the questions as part of that is: What happens if you give sum_pairs a list with an odd length?.

My approach to solving that was by introducing another function below which basically returns false if the length of a list is odd because sum_pairs is ideally meant to calculate the length of a list with even length and what sum_pairs function does is that it takes a list and returns a list which is half the length of the original list. Additionally, each element in the resultant list is the sum of two elements from the input list.

def sum_pairs([h | t]) when length([h | t]) |> Integer.is_odd == true, do: false

The overall solution looks like:

  @doc """
  Add the ability to calculate the sum of pairs of elements in a list
  ## Examples
    iex> Lists.sum_pairs([])
    []
    iex> Lists.sum_pairs([5, 3, 8, 9])
    [8, 17]
    iex> Lists.sum_pairs([5, 3, 8])
    false
  """
  def sum_pairs([]), do: []
  def sum_pairs([h | t]) when length([h | t]) |> Integer.is_odd == true, do: false
  def sum_pairs([h1, h2 | t]), do: [h1 + h2 | sum_pairs(t)]

I’m curious to learn how you’d go about solving this irrespective of whether you’ve done the course or not. I wanted to look at the course related forum to see if somebody asked a similar question but I didn’t find a search functionality in the course forum to easily search for a related question. @pragdave it would be great to get your take on this as well if feasible. Thank you for the course Dave, really enjoying it so far :slight_smile:

Thank you.

1 Like

I’d iterate over pairs and sum the last element as if with a 0 (nothing) or drop it if there is no pair element for it so that I can avoid calling length. I’d avoid returning false since it makes for a rather unintuitive API.

defmodule Lists do
  @spec sum_pairs([integer]) :: [integer]
  def sum_pairs([]), do: []
  def sum_pairs([_unpaired_element] = t), do: t # [_unpaired_element + 0] or drop it: []
  def sum_pairs([h1, h2 | t]), do: [h1 + h2 | sum_pairs(t)]
end
iex(2)> Lists.sum_pairs([])
[]
iex(3)> Lists.sum_pairs([5, 3, 8, 9])
[8, 17]
iex(4)> Lists.sum_pairs([5, 3, 8])
'\b\b' # [8, 8]
2 Likes

Thank you for sharing your solution to this :slight_smile: . I definitely feel your solution is a more suitable one in terms of how the final result should look like when dealing with a list of odd length. I would personally prefer the solution with adding 0 to the last element of the list when dealing with a list of odd length.

Also +1 for adding some typespecs to your code :slight_smile:. I forgot that in my solution.