exercism/elixir/perfect-numbers/lib/perfect_numbers.ex

42 lines
1.1 KiB
Elixir
Raw Normal View History

2024-07-08 00:55:46 +00:00
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