using System;
using System.Linq;
public enum Classification
{
Perfect,
Abundant,
Deficient
}
public class PerfectNumbers
{
public static Classification Classify(int number)
{
if (number < 1)
throw new ArgumentOutOfRangeException(nameof(number));
var sumOfFactors = Enumerable.Range(1, number / 2)
.Where(factor => number % factor == 0)
.Sum();
if (sumOfFactors < number)
return Classification.Deficient;
if (sumOfFactors > number)
return Classification.Abundant;
return Classification.Perfect;
}
}
The first step is to check the number
for validity:
if (number < 1)
throw new ArgumentOutOfRangeException(nameof(number));
The next step is to calculate the sum of the number's factors.
A factor is a number that you can divide another number with and not end up with a remainder, which we can check using the modulo (%
) operator: number % factor == 0
.
We then need to decide which numbers could possibly be factors.
For the lower bound, we can use 1
, as that is always the smallest factor.
For the upper bound, we can leverage the fact that the second lowest factor is 2
, which means that any numbers greater than number / 2
cannot be factors.
We can use the Enumerable.Range() method to iterate over the possible factors, then use Where() to select only valid factors and then finally sum them via the Sum() method:
var sumOfFactors = Enumerable.Range(1, number / 2)
.Where(factor => number % factor == 0)
.Sum();
Then finally we can apply the logic to classify the perfect number via some if
statements:
if (sumOfFactors < number)
return Classification.Deficient;
if (sumOfFactors > number)
return Classification.Abundant;
return Classification.Perfect;
Shortening
You could use the ternary operator to replace the if
statements:
return sumOfFactors < number ? Classification.Deficient :
sumOfFactors > number ? Classification.Abundant :
Classification.Perfect;
Combining Where and Sum vs. using Sum only
Instead of using Where and then Sum we could actually implement this by using Sum only.
We can provide the Sum with a lambda that tells it to keep every number that is a factor and use a 0
in place of every number that isn't, effectively disregarding it when summing:
var sum = Enumerable.Range(1, number - 1)
.Sum(n => number % n == 0 ? n : 0);
This also uses the aforementioned ternary operator.