small medium large xlarge

• Write `max(list)` that returns the element with the maximum value in the list. (This is slightly trickier than it sounds.)

A Possible Solution</summary>

```# Our solution uses the built-in max/2 function, which
# returns the larger of its two numeric arguments.
# Although it isn't necessary, we call it as
# `Kernel.max` to avoid confusion

defmodule MyList do

# max([]) is undefined...

# max of a single element list is that element
def max([x]), do: x

# else recurse

end

IO.puts MyList.max([4])       #=> 4
IO.puts MyList.max([5, 4, 3]) #=> 5
IO.puts MyList.max([4, 5, 3]) #=> 5
IO.puts MyList.max([3, 4, 5]) #=> 5
```

</details>

I see that I have a long way to go to learning to do this stuff elegantly. Here is my initial solution, followed by three important things I learned comparing my code to Dave’s:

``````defmodule MyList do
defp _max([], greatest), do: greatest
defp _max(a, b) when a >= b, do: a
defp _max(_a, b), do: b
end
``````

1. Kernel.max exists. I should have known better and looked that up rather than trying to roll my own into my function.

2. I don’t always have to use `[]` as the place I break the recursion when processing lists. In this case `[x]` makes perfect sense and would eliminate some of the cruft in my answer.

3. Probably most importantly, I started thinking at the head of the list and what to do with the rest rather than thinking about what things would look like with the recursion “unrolled”. Dave’s code pretty much looks at what would be the last element of the list, calls it the max, and rolls that up. Mine starts with the head, rolling it down, and keeping that messy `greatest` around for comparison.

This is great stuff, and I love these challenges over just looking at the “right” way of doing it and saying, “Yes, I understand that” without really learning how to arrive at that understanding. Thanks, Dave!

Scott, don’t feel bad about rolling your own function. You wouldn’t have learned how it worked, otherwise.

My first stab at this problem actually used Kernel.max. Then I did:

``````def max([]), do: 0
def max(list), do: Enum.sort(list) |> Enum.reverse |> hd
``````

But I still tried to come up with a version without calling any built in functions because I kinda felt like I was cheating lol.

However, your implementation would result in an error if called with an empty list. It should be something like:

``````def max(list), do: _max(list, 0)
defp _max([], greatest), do: greatest
defp _max([ _head| tail ], greatest), do: _max(tail, greatest)
``````

Apologies if you intended it to raise an error with an empty list though.

Dave, might I suggest that the solutions be actual implementations where possible instead of calling existing functions? I think it would help a great deal to see the proper implementations. Great book, btw.

@Scott, my solution was very similar to yours, except I used guard clauses. I agree that @Dave’s is easily better, but when I tackled this exercise my brain was in ‘use what you know’ not ‘look in the docs for help’ mode. =-)

``````defmodule MyList do
defp _max([], e), do: e
end
``````

My solution maintained the maximum value as the head of the list, avoiding the need for an additional function parameter…

``````defmodule MyList do
def max([ max ]), do: max
def max([ max | [head|tail] ]) when max >= head, do: max([ max | tail ])
end
``````

Is there a Negative Infinity constant (or concept) in Elixir? With that, I think it could be written in terms of the reduce function that has already been defined, like this:

``````  def max(list), do: reduce(list, -10_000_000_000, _max(&1, &2))
defp _max(x, y) when x > y, do: x
defp _max(_, y), do: y
``````

Just insert the negative infinity constant in place of the negative 10 billion above.

It turns out you don’t need a negative infinity concept: just pass in the head value for the first comparison.

Here’s an alternate implementation:

``````def max(list), do: reduce(list, hd(list), &(&1 > &2 && &1 || &2))
``````
``````def max([head | []]), do: head
``````

Why would you avoid built-in functions? That’s what they’re for. The assignment is to get the max value from a list, not to rewrite the max function.

Very similar to the others solutions:

``````defmodule MyList do
def max([]), do: {:error, "INPUT_ERROR"}
def max([first]), do: first
def max(list) do
[first | [second | tail]] = list
max([get_max(first, second) | tail])
end

defp get_max(first, second) when first > second do
first
end
defp get_max(_, second), do: second
end
``````

Here is my version, using a guard clause instead of the builtin max function:

``````defmodule MyList do
def max([x]), do: x
def max([x, y]) when x > y, do: x
def max([x, y]), do: y
end
``````
``````
defmodule Mylist do
end

max([max_num | tail])
end

end

end

``````
``````defmodule MyList do
def max([]),                     do: []
def max([max]),                  do: max
def max([a,b|tail]) when a < b,  do: max([b | tail])
def max([a,_b|tail]),            do: max([a | tail])
end
``````

This is what I used. Not sure where it fits in the hierarchy:

``````def max([]), do: IO.puts("Undefined.")
``````

Used an accumulator, then had a hard time getting rid of it.

Lots of interesting solutions above.

``````defmodule MyList do
# def max([]) is undefined
defp _max([], max_value), do: max_value
defp _max([ _head | tail ], max_value)                      , do: _max(tail, max_value)
end
``````

Rolled my own max as well. Used an accumulator to pull it off.

``````defmodule MyList do
def max(list), do: _max(list, 0)
def _max([], n), do: n
def _max([head | tail], acc) when head < acc, do: _max(tail, acc)
end
``````

Looks like I also have a ways to go about thinking “the functional way” :)

My first shot, I didn’t know about the inbuilt max/2 function, and also used an accumulator.

``````defmodule MyList do
end

defp _max([], biggest) do
biggest
end

end

defp _max([_|tail], biggest) do
_max(tail, biggest)
end
end
``````

Also, my way doesn’t handle an empty list as input. Derp.

``````defmodule MyList do
def max([a]), do: a
def max([a,b | tail]) when a > b do
max([a | tail])
end
def max([a,b | tail]) when b >= a do
max([b | tail])
end
end
``````
``````defmodule ListAndRecursion do

def list_max([], val), do: val

def list_max([h | t], val) when h > val, do: list_max(t, h)

def list_max([h | t], val) when h <= val, do: list_max(t, val)

end
``````

Based on Dragos Tudorache

``````defmodule MyList do
def max(list), do: _max(list, 0)
defp _max([head | tail], val) when head <= val, do: _max(tail, val)
defp _max([], val), do: val
end
``````

But this thing does not work well with negative numbers :( This only prove me that I need to learn a lot about functional programming and recursive things

My solution

``````defmodule MyList do
def max([]), do: nil
def max([single | []]), do: single
def max([first | [second | rest]]) do
if (first > second) do
max([first | rest])
else
max([second | rest])
end
end
end

IO.inspect MyList.max [1,5,9, 10,4,2]  # Prints 10
``````

I supposed that Elixir must have max(a, b) function, but didn’t search for it and wrote without using it:

``````  defmodule ListFuncs do
def max([f]), do: f
def max([f, s | rest]) when f < s, do: max([s | rest])
def max([f, _ | rest]), do: max([f | rest])
end
``````

My Solution

`````` def max(list), do: _max(list, 0)
defp _max([], val), do: val
``````
``````defmodule MyList do
def mymax(list, m \\ 0)
def mymax([], m), do: m
end
mymax(tail, m)
end
end

IO.puts MyList.mymax([5, 2, 90, 22])  # => 90
``````

My version:

``````defmodule MyList do

def max(list), do: _max(list, 0)

defp _max([], value), do: value
end
_max(tail, value)
end
end
``````

I found Kernel.max() in the docs. My version should be tail recursive.

``````defmodule MyList do
# max([]) is an input error. Do I need/how to throw error?

def max([x]), do: x

defp _max([x], max), do: Kernel.max(max, x)

end
``````
``````defmodule MyList do
def max(list) do
_max(list, hd(list))
end

defp _max([], value), do: value

defp _max([ head | tail ], value) when head > value do
end

defp _max([head | tail], value) do
_max(tail, value)
end

``````

My solution is much simpe, it handle the negative value and does not require any more parameter but the LIST only. Using by: MyList.max [123,4,5,6,555]

``````
defmodule MyList do
def max(alist), do: (
mymax(alist, List.first(alist))
)
def mymax([], val), do: (
val
)
)
mymax(tail, val)
)
end

``````

The 2 first elements of the list are reduced by Kernel.max recursively until the list is composed of one single element which is the biggest.

``````  def mapmax([head | _tail]), do:  IO.puts("the max number is #{head}")

end
``````

Here’s mine. Maybe not the best, but I wanted to try it without resorting to the Kernel module.

``````def max(list), do: _max(list, 0)
defp _max([], val), do: val
defp _max([ h | t ], val), do: _max(t, h > val && h || val)
``````

```defmodule MyList do
def max([], value \\ 0) do
value
end
end
MyList.max tail, value
end
end
```
```defmodule MyList do
def max([head|tail], value \\ 0) do
cond do
tail == []    -> value
head <= value -> MyList.max(tail, value)
end
end
end
```

The shortest version:

```defmodule MyList do
def max(list), do: List.last Enum.sort list
end
```

My Solution

``````defmodule MyList do
def max([h]), do: h
def max([h | t]) when h > hd(t), do: max [h | List.delete_at(t, 0)]
def max(l = [h | t]) when h <= hd(t), do: max List.delete_at(l, 0)
end
``````

My solution:

``````def my_max(list), do: _my_max(list, 0)

defp _my_max([], cur_max), do: cur_max
defp _my_max([ head | tail ], cur_max) when head <= cur_max do
_my_max tail, cur_max
end
defp _my_max([ head | tail ], cur_max) when head > cur_max do
end
``````

I know `Kernel.max` exists, but so does `Enum.max`, so I couldn’t draw the line for what would constitute “cheating” and rolled my own.

Looks like most people preferred to use guards, here’s a different way:

``````
def max([]), do: 0
def max(list), do: _max(list, 0)
defp _max([], max), do: max
defp _max([ head | tail], max) do
cond do
head < max -> _max(tail, max)
end
end
``````
``````def max([]), do: {:error, :undefined}
defp _max([], max), do: max
defp _max([_ | tail], max), do: _max(tail, max)
``````

Only need to check if head > max.

It seems like this is a variation on reduce that needs specialized initial conditions, so here’s what I came up with. (Btw, calling with an empty list doesn’t really make sense, so maybe just not matching the empty list, as some others have done, is better than returning nil?)

``````  def max([]), do: nil
``````

I really wanted to see if I could do this without looking up docs - took me a while but it was worth figuring out how simple it really was even without the kernel function.

``````  def max([max_val]), do: max_val
def max([ max_val | [ head | tail ]]) when max_val >= head, do: max([ max_val | tail])
def max([ max_val | [ head | tail ]]) when max_val <= head, do: max([ head | tail])
``````
``````defmodule MyList do
def max(list), do: _max(list, 0)

#Private functions
defp _max([], maxnum),            do: maxnum
end

#Calling the functions...
#Return the element with a maximum value in the list.
#Sum of an empty list, []: assign a 0.
IO.puts MyList.max []               #=> 0
IO.puts MyList.max [1, 2, 3, 1]    #=> 3
``````

Please note: max(maxnum, head) is the Kernel.max() function. The arity of max(maxnum, head) is different from the local max() - so it still worked. Obviously for readability should have used Kernel.max() rather than just max().

``````defmodule MyList do
def max(list) do
_max(list, 0)
end

#Private functions
defp _max([], maxnum) do
maxnum
end

defp _max([head | tail], maxnum) do
end

end

maxnum
end
end

#Calling the functions...
#Return the element with a maximum value in the list.
#Sum of an empty list, []: assign a 0.
IO.puts MyList.max []              #=> 0
IO.puts MyList.max [1, 2, 3, 1]    #=> 3
``````

This was a second solution with a locally defined _findmax() rather than an Elixir library Kernel.max().

Here’s mine:

```defmodule ListRec do

def max([h|t]) do
maxp(t, h)
end

defp maxp([], x), do: x

defp maxp([h|t], cm) when h > cm,  do: maxp(t, h)

defp maxp([h|t], cm) when h <= cm, do: maxp(t, cm)

end
```

`cm` stands for “current maximum”. I can’t figure out how to do it without it, and therefore without those two helper private functions.

that’s my solution, also works with negative numbers:

``````defmodule MyList do

def max(list),   do: _max(list, 0)

defp _max([], maxres),              do: maxres

defp _max([ head | tail ], maxres) when head > maxres do

_max(tail, maxres)

end

defp _max([ head | tail ], maxres) when head < maxres do

_max(tail, maxres)

end

end
``````

I see when I read “write a `max(list)` function, that doesn’t necessarily mean that the first argument has to be `list`.

Anyway, here’s my solution:

``````defmodule MyList do
def reduce([], value, _), do: value

def reduce([head | tail], value, func) do
end

def max([]), do: nil

def max([x]), do: x

greater_than = fn
(x, y) when x > y -> x
(x, y) when y > x -> y
end

end
end
``````
``````def mmax([], curMax), do: curMax
``````

Note that I used mmax to avoid a conflict with Erlang max (likely a better way to avoid such conflicts but I am new to this, still I think the code above is fairly clean and understandable).

I wanted to reuse the reduce function

``````~~~
defmodule MyList do
def max(list=[h|_]) do
Enum.reduce(list, h,
fn
new,  prevMax when new > prevMax -> new
_,    prevMax                    -> prevMax
end
)
end
end

~~~
``````

Simple and direct: head is the max accumulator, using only one guard.

``````defmodule MyList do
def max([max]), do: max
def max([max | [head | tail]]) when max >= head, do: max([max | tail])
end
``````

# It must deal with negative numbers also

``````defmodule MyList do

def max([]), do: []
defp _max([], value), do: value
_max(tail, value)
end
end

IO.puts MyList.max []                 # []
IO.puts MyList.max [3]                # 3
IO.puts MyList.max [10, 1, 3, 5]      # 10
IO.puts MyList.max [-10, 1, 3, -5]    # 3
IO.puts MyList.max [-10, -1, -3, -5]  # -1
``````
``````defmodule MyList do
def max([head | [] ]) do
end
max(new_list)
end
def get_lower(current, [head | tail]) do
current
else
end
end
``````

Without using stuff that wasn’t covered in the book yet:

``````defmodule MyList do
def maxval(list), do: _maxval(list, 0)
defp _maxval([], value), do: value
defp _maxval([head | tail], value) when head <= value do _maxval(tail, value) end
end
``````
```defmodule MyList do
def max(list \\ []), do: _max(list,0)
defp _max([], maxval), do: maxval
defp _max([_head|tail], maxval), do: _max(tail, maxval)
end

IO.puts MyList.max([5, 4, 3]) # 5
IO.puts MyList.max([4, 5, 3]) # 5
IO.puts MyList.max([3]) # 3
IO.puts MyList.max([]) # 0
IO.puts MyList.max() # 0

```

Like a lot of others I built my own, here’s my effort:

``````def max(list), do: _max(list, 0)
defp _max([], greatest), do: greatest
defp _max([head | tail], greatest), do: _max(tail, greatest)
``````

Hi, I don’t know why nobody used pattern matching to solve the problem. I ask my selfe, is it a bad code quality when you use pattern matching instead of using when as a condition query? My solution is:

``````  def max(list), do: _max(list)

defp _max([]), do: []
defp _max([], value), do: value

defp _larger(false, _, value), do: value
``````

Similar apporach to Dave, but we did just learn the pipe character right before this.

``````defmodule MaxList do

def maxlist([num]), do: num

maxlist(tail)
end

end
``````
``````defmodule MyList do
def max(list), do: _max(list, 0)

defp _max([], value), do: value
defp _max([ head | tail ], value) when head <= value, do: _max(tail, value)
end
``````
``````def max([x]), do: x
``````

Probably already post by someone but this is the best solution I can find without using max builtin:

``````def maxlist([head]) do
end

end

end
``````

I think lesson here is that there are functions not defined for all input. In this case, what should be the value of maxlist([])? There is no proper definition for that.

Another lesson is that recursion needs to reduce the problem, in this case getting rid of one list element, but is not needed that we remove always the first one.

Sharing my solution

```defmodule Play do
def max([]), do: 0
def max([h]), do: h
def max([h|[a|b]]) do
cond do
h > a -> max([h|b]
h < a -> max([a|b])
end
end
end
```

or

```def max([]), do: 0
def max([h]), do: h
def max([h|[a|b]]) when h > a, do: max([h|b])
def max([h|[a|b]]) when h < a, do: max([a|b])
```
```defmodule MyList do
def max([]) do
IO.puts "The list is empty."
end

def max([ head | [] ]) do
end

def max([ head | tail ]) do
if head < max(tail), do: max(tail)
end
end
```

I had to post this solution. The first task I didn’t look at the forum for answers

```defmodule MyList do

def max(list) do
_max(list, 0)
end

defp _max([], largest) do
largest
end

end

_max(tail, largest)
end

end
```
```defmodule MyList
def finder(list, _) when list == [], do: nil
def finder([h | []], _), do: h
def finder([h | [x | t]], fun) when is_function(fun, 2) do
if fun.(h, x), do: finder([h | t], fun), else: finder([x | t], fun)
end

def max(list), do: finder(list, &(&1 > &2))
def min(list), do: finder(list, &(&1 < &2))
def shortest(list), do: finder(list, &(String.length(&1) < String.length(&2)))
def longest(list), do: finder(list, &(String.length(&1) > String.length(&2)))
end
```
``````defmodule MyList do
def reduce([], value, _) do
value
end
def reduce([head | tail], value, func) do
end

def max([]) do
IO.puts "The list is empty."
end
defp _max(x, y) when x > y, do: x
defp _max(_, y), do: y
end

``````
``````defmodule MyList do

def _max([], max), do: max
def _max([head | tail], max) when max >= head, do: _max(tail, max)

end

``````

What do you think about following solution?

``````~~~
def custom_max([entry]) do
entry
end

current_max = custom_max(tail)
else
current_max
end
end
~~~
``````
``````def max([head | []]),        do: head

defp _max(x, y) when x >= y, do: x
defp _max(x, y),             do: y
``````

@Victor Solis I have see you answers, and other answers which has a value with default value `0`, will not correct when list values are `negative number `

@Elias Perez You should concern about the multiple values equal case.

``````  def max([]), do: IO.puts "The list is empty."
cond do
end
end
``````

Heres my answer, interesting to see so many variations.

``````  def max(list), do: _max(list, 0)

# Private methods

defp _max([], max), do: max
defp _max([head | tail], max), do: _max(tail, max)
``````

It’s been nice to see so many different solutions. I didn’t even think about looking for something like `Kernel.max`

``````defmodule MyList do
def max([ head | tail ]) do
end

defp _max([], memory) do
memory
end

end

defp _max([ _head | tail], memory) do
_max(tail, memory)
end
end
``````

Moving the head through the tail and making comparisons :)

``````defmodule MyList do
end
def max( [ head | tail ] ) when head <= tail, do: max( tail )
end
``````
``````def max(lista), do: _max(lista, List.first(lista))

defp _max([], max), do: max
defp _max([h|t], max) when h>=max, do: _max(t, h)
defp _max([h|t], max) when h<max, do: _max(t, max)
``````

Yet another solution

``````defmodule Mylist do

def max([]),                 do: nil

def max([a]),                do: a

def max([a, b]) when a >= b, do: a

def max([_, b]),             do: b

def max([a | b]),            do: max([a, max(b)])

end
``````
``````    def max(list_) do
end

defp _max([], curr_max) do
IO.puts("Got in the end... #{curr_max}")
curr_max
end

defp _max([head | tail], curr_max) do
curr_max = if (head > curr_max) do
curr_max
else
curr_max
end
_max(tail, curr_max)
end
``````

Seems like I am in the minority that used if / else, little bit imperative still I guess :)

``````  def max([head | tail]) do
end

defp _max([], maximum), do: maximum

end

_max(tail, curr_max)
end
``````
`````` def max(list), do: _max1(list, 0)

defp _max1([], val), do: val
defp _max1([ head | tail ], val), do: if(head > val, do: _max1(tail, head), else: _max1(tail, val))
``````

I came up with this solution:

``````defmodule MyList do
def max([]), do: nil
def max([ head | [ tail | [] ] ]), do: tail
def max([ head | [ neck | tail ] ]) when head >= neck, do: max([ head | tail ])
def max([ head | [ neck | tail ] ]), do: max([ neck | tail ])
end
``````
``````
defmodule MyList do

# Principal function

def maxu(a, start \\ -1_000_000_000 )

def maxu([], start), do: start

def maxu([head | tail], start) do
end

# private function

def func1(x,y) when x > y do
x
end
def func1(x,y) when x <= y do
y
end

end

``````

I came up with a completely different approach that did not use any external libraries. What do you think?

``````defmodule MyList do

def max(list), do: _max(list, 0)

defp _max([], value) do
value
end

getmax = fn(a, b) -> if(a > b, do: a, else: b) end

end

end
``````
``````def SpecialList do
def lmax(list, max \\ 0)
def lmax([], max), do: max
def lmax([ head | tail ], max) when max >= head, do: lmax(tail, max)
end
``````
``````defmodule MyList do
def max(list), do: _max(list, 0)

defp _max([], max), do: max
end
defp _max([_head | tail], max) do
_max(tail, max)
end
end
``````

So basically this was my take at this exercise… I take advantage of the fact that an empty tuple always ranks lesser than any tuple that has something in it.

``````negative_infinity = {}
number = {0}
infinity = {:infinity}

negative_infinity < number
# true
number < infinity
# true
``````

And this is the code:

``````def my_max(list, negative_infinity \\ {})