# Project Euler (problem 2)

I’m just learning Elixir but find it really fun, nevertheless it’s easy to produce crappy code when there is no one to do some review. Thus i ask you nicely to tell me how can I improve it to be more readable, or maybe faster, better?

``````defmodule Two do
def fibonacci_even_sum do
Stream.unfold({1, 2}, fn({n, m}) -> if n > 4_000_000, do: nil, else: {n, {m, n + m}} end)
|> Enum.reduce(0, fn(n, acc) -> if rem(n, 2) == 0, do: n + acc, else: 0 + acc end)
end
end

IO.inspect Two.fibonacci_even_sum
``````

I’ll be grateful for any review

I almost forgot… original problem:

``````Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
``````
1 Like

I’m also just getting my feet wet with Elixir and I’ve been trying to approach problems like this as if I were going to be applying them to larger systems/had other team members looking at my code later.

Nice use of unfold! Lets pull it out into its own function.

``````defmodule Two do
def fibonacci_even_sum do
fibonacci_sequence
|> Stream.take_while(&(&1 < 4_000_000))
|> Enum.reduce(0, &sum_even/2)
end

def fibonacci_sequence do
Stream.unfold({1,1}, fn {a,b} -> {a, {b, a + b}} end)
end

def sum_even(num, acc) do
if rem(num, 2) == 0, do: acc + num, else: acc
end
end
``````

I’ve doubled the amount of lines your solution would take but it makes your intentions more obvious.
Piping into Stream.take_while allows us to turn your unfold into a more generally useful endless stream while only taking as many as we need.

I’m conflicted on pulling the reduce function out into its own function, I’m not really sure what the general best practice is there? I’d like to hear more from people on that.

Hope this helps!

2 Likes

If we’re going the `Stream`ing route you may as well use `Stream.filter`.

``````def fib_even_sum(limit) do
fibonacci_sequence
|> Stream.take_while(&(&1 < limit))
|> Stream.filter(&(rem(&1, 2) ==0))
|> Enum.sum
end
``````
4 Likes

Yeah, they are much more readable So much more learning before me, but when i read how can my ugly code be transformed into something beautiful i think i’ll switch to Elixir in my Engineering thesis

1 Like

I was looking for the Stream.take_while and i a bit confused how it work. I was putting :

a = [1,2,3,4,5,6,7,8,9,10,15,16,17,19,20]
and then
b = Stream.take_while(a,fn (a) -> a <10 end) but doesn’t return anything , but when i do

b |> Enum.sum , it return the correct value (45) .

Also look that enum and stream have a take_while function , what are the difference between this?

1 Like

Enum early operates on the input, streams do so lazily.

2 Likes

Streams are lazy by design. You need either an Enum call or a Stream.run at the end of the pipeline to actually cause it to execute.

2 Likes