42 lines
1.1 KiB
Elixir
42 lines
1.1 KiB
Elixir
|
defmodule PerfectNumbers do
|
||
|
@doc """
|
||
|
Determine the aliquot sum of the given `number`, by summing all the factors
|
||
|
of `number`, aside from `number` itself.
|
||
|
|
||
|
Based on this sum, classify the number as:
|
||
|
|
||
|
:perfect if the aliquot sum is equal to `number`
|
||
|
:abundant if the aliquot sum is greater than `number`
|
||
|
:deficient if the aliquot sum is less than `number`
|
||
|
"""
|
||
|
@spec classify(number :: integer) :: {:ok, atom} | {:error, String.t()}
|
||
|
def classify(number) when number <= 0, do: {:error, "Classification is only possible for natural numbers."}
|
||
|
def classify(1), do: {:ok, :deficient}
|
||
|
def classify(number) do
|
||
|
sum =
|
||
|
number
|
||
|
|> divisors()
|
||
|
|> Enum.sum()
|
||
|
|
||
|
cond do
|
||
|
sum == number ->
|
||
|
{:ok, :perfect}
|
||
|
|
||
|
sum > number ->
|
||
|
{:ok, :abundant}
|
||
|
|
||
|
sum < number ->
|
||
|
{:ok, :deficient}
|
||
|
end
|
||
|
end
|
||
|
|
||
|
defp divisors(number) do
|
||
|
for i <- 1..round(number ** 0.5), reduce: [] do
|
||
|
acc -> if rem(number, i) == 0, do: [i, div(number, i) | acc], else: acc
|
||
|
end
|
||
|
|> Enum.uniq()
|
||
|
|> Enum.sort()
|
||
|
|> Enum.drop(-1)
|
||
|
end
|
||
|
end
|