Heron Rossi
Heron Rossi

Reputation: 701

Elixir: sum 2+ digit number

I'm studying functional programming with Elixir and came across the following exercise:

"You are given a two-digit integer n. Return the sum of its digits."

The solution I came up looks a bit "hairy". I wonder if someone could give some advice into Elixir std lib functions/module and provide a better solution. I know I could just go with n%10 + Math.floor(n/10)(js) but Id' like to know if a solution using Elixir functions would be more or less what I came up with:

def addTwoDigits(n) do
   n |> Integer.to_string 
     |> String.split("") # Number 44 would give a list ["",4,4,""]
     |> Enum.filter(&(&1 != ""))
     |> Enum.map(&(String.to_integer(&1)))
     |> Enum.reduce(&(&1+&2))
end

Upvotes: 1

Views: 2080

Answers (3)

Ronan Boiteau
Ronan Boiteau

Reputation: 10138

You should avoid unnecessary operations (conversion to string, conversion to list, etc.).

I'd go with the following, using div/2 & rem/2 in a recursive function:

def addTwoDigits(n) do
  if n > 0, do: rem(n, 10) + addTwoDigits(div(n, 10)), else: n
end

I used this to compare our functions:

  • your function runs in ~16 μs
  • the function above runs in ~4 μs

By working with integers you avoid useless conversions/iterations & get a function that computes your result ~4 times faster!

Upvotes: 1

Kevin Johnson
Kevin Johnson

Reputation: 1970

Easiest and closest to your initial thought, would be by leveraging the following function:

Integer.digits(123)
[1, 2, 3]

to obtain each individual digit as documented here

You can then simply do:

def sum_digits_in_number(n) do
   n
   |> Integer.digits
   |> Enum.sum
end

Upvotes: 2

Aleksei Matiushkin
Aleksei Matiushkin

Reputation: 121010

Since it’s an exercise / learning example, I would assume the answer expected would be a function with many clauses:

defmodule M do
  def add(num, acc \\ 0)
  def add(num, _acc) when num > 99, do: raise("Invalid #{num}")
  def add(num, acc) when num < 10, do: acc + num
  def add(num, acc), do: add(rem(num, 10), acc + div(num, 10))
end

IO.puts M.add(35)
#⇒ 8
IO.puts M.add(5)
#⇒ 5
IO.puts M.add(88)
#⇒ 16
IO.puts M.add(101)
#⇒ ** (RuntimeError) Invalid 101

This is definitely a huge overkill for this particular task, but think how easy is to make this code to sum integers having 3 numbers (unlike any other non-functional approach.)

Upvotes: 1

Related Questions