# Project Euler (problem 1)

I just started reading about Elixir few days ago, an I’m fascinated. I programmed in Python, Java, and i work in Ruby. Never before i wrote in functional language.

I read most of tutorial, did elixir koans, and now i tried project euler

``````defmodule One do

def sum_of_multiples(n) do
n = n - 1
if n == 0 do
0
else
if rem(n, 3) == 0 do
sum_of_multiples(n, n - 1)
else
if rem(n, 5) == 0 do
sum_of_multiples(n, n - 1)
else
sum_of_multiples(0, n - 1)
end
end
end
end

def sum_of_multiples(accumulator, n) do
if n == 0 do
accumulator
else
if rem(n, 3) == 0 do
sum_of_multiples(accumulator + n, n - 1)
else
if rem(n, 5) == 0 do
sum_of_multiples(accumulator + n, n - 1)
else
sum_of_multiples(accumulator, n - 1)
end
end
end
end

end

IO.puts One.sum_of_multiples(1000)
``````

Above is my working code. How can i rewrite this to use pattern matching instead of this ugly if else?

I tried like this also:

``````Enum.map(1..999, fn n -> if rem(n, 3) == 0 or rem(n, 5) == 0, do: n, else, do: 0, end) |> Enum.sum |> IO.puts
``````

But first of all there is syntax error i’m unable to correct on my own

I somehowo managed to do that:

``````Enum.map(1..999, fn n -> if(rem(n, 3) == 0 or rem(n, 5) == 0, do: n, else: 0) end) |> Enum.sum |> IO.puts
``````

But still don’t know how to rewrite those functions

1 Like

There isn’t really much you can do or win by pattern matching in this exercise.

The real thing that would make your code functional is to consider functions as data and start passing them around.

I’d try to start from scratch, having open the docs of `Enum`, `Range` and perhaps `Stream` but the last one can get substituted by `Enum` easily.

If you want to become spoiled by the exercise, just say a word, and I will link to my solution of a similar exercism exercise.

1 Like

I’ve come with

``````Enum.map(1..999, fn n -> if(rem(n, 3) == 0 or rem(n, 5) == 0, do: n, else: 0) end) |> Enum.sum |> IO.puts
``````

And i would really like to see how you did it in functional way. At this point of my leaning Elixir path, I believe there is still not many room for challenge, and learning by reading others code will give me much more then hours of trying to do it on my own.

1 Like

That’s a solid functional solution. I think using Enum.filter instead of Enum.map is slightly more intention-revealing though.

2 Likes

Yeah, my solution is pretty much like that, but a little bit more generic, as the exercism variant is not about multiples of 3 and 5, but about the sum of the multiples of a list of numbers.

I think now you are ready to compare a bit: http://exercism.io/submissions/4095800ec24b497cb3c11cf81be7e216

1 Like

Awesome! So Insightful with the &1 Enum.any? and Stream.filter

1 Like

Im also starting Project Euler, great solutions, i need to get familiar with enum and streams functions . Here is my aproach , basic recursion

``````defmodule Euler1 do

def suma(numero, acc) when numero>0 do
if rem(numero,5) == 0 or rem(numero,3)==0 do
acc=acc+numero
end
suma(numero-1,acc)
end

def suma(numero,acc) do
acc
end
end
``````
1 Like

Here my recursive approach.

``````defmodule Euler1 do
def sum(0), do: 0
def sum(n) when rem(n-1,3) == 0 or rem(n-1,5) == 0, do: n-1 + sum(n-1)
def sum(n), do: sum(n-1)
end
``````
3 Likes

What you are dooing here is called an imperative assigenment and is deprecated in elixir 1.3 and will be removed. With other words, in a couple of versions no assignment will leak scope anymore. (Maybe I’m confusing some version numbers here, but imperative assignments will vanish)

Prefered way to do it from then on is the following:

``````acc = if rem(n, 3) == 0 or rem(n, 5) == 0, do: acc + n, else: acc
``````

Even better would be an approach that uses top level guards and pattern match similar to @danseid’s solution. But even that is not perfect because it is not tail call recursive…

2 Likes

@NobbZ you are right, this would be a TCOed solution:

``````defmodule Euler1 do
def sum(n), do: sum(n-1, 0)
def sum(0,acc), do: acc
def sum(n, acc) when rem(n,3) == 0 or rem(n,5) == 0, do: sum(n-1, n+acc)
def sum(n, acc), do: sum(n-1,acc)
end
``````
4 Likes

good job! I believe your solution might be improved further by making all variants that take two parameters (in other words: the variants that are only used internally) private. In Erlang/Elixir, I believe the naming convention for such a private variant that takes more arguments is to prefix it with `do_`, e.g. `do_sum`:

``````defmodule Euler1 do
def sum(n), do: do_sum(n-1, 0)
defp do_sum(0,acc), do: acc
defp do_sum(n, acc) when rem(n,3) == 0 or rem(n,5) == 0, do: do_sum(n-1, n+acc)
defp do_sum(n, acc), do: do_sum(n-1,acc)
end
``````

Have a nice day,

~Qqwy

2 Likes

Since I am reading a lot of erlang in different closed source projects (and only a couple of open source) for an universitary project, I can tell, that I do see everything there, for me it does not seem as if there is any community idiom on the naming on such functions.

I’ve seen the following:

• Prefix `do_`
• Prefix `_` only
• Use a completely different prefix
• Just use the same name as in the function without accumulator(s)
• Use a complete different name

OK, I have to admit, that I’ve seen especially the last “convention” exclusively in environments where also languages are used which do only identify functions by name, not by arrity or type.

Personally I do prefer to use exactly the same name for functions that do the same, so `map/2` would call `map/3` in my code.

Most of the code that has been evaluated by me so far do use one style consistent (except some legacy parts noone wants to touch unless really really necessary ;)). And I do think beeing consistent through out the project is more important than trying to follow some community guide lines which do constantly change and update according to the languages evolution.

3 Likes

I thought function clauses that take a different amount of parameters where still ‘linked somehow’, but this is not true. Therefore, it is entirely possible to define `sum/2` as private while keeping `sum/1` public.

And that’s how you learn something new every day. Thank you!

(P.S: I’m actually happy I’ve been proven wrong about the convention of `do_` prefixing, as I like the `_` prefix one better.)

I completely agree .

1 Like

With `..` (range) and list comprehension:

``````defmodule Euler do
def euler1(range, x, y) do
(for n <- 1..range, rem(n, x) === 0 or rem(n, y) === 0, do: n)
|> Enum.sum
end
end``````
3 Likes
``````Enum.to_list(1..1000)
|> Enum.filter(fn(x) -> (rem(x, 3) == 0) || (rem(x,5) == 0 ) end)
|> Enum.sum
``````

or even better

``````multiples_of_three_and_five = fn(x) -> (rem(x, 3) == 0) || (rem(x,5) == 0 ) end

Enum.to_list(1..1000)
|> Enum.filter(multiples_of_three_and_five)
|> Enum.sum

``````
3 Likes