Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 82 additions & 45 deletions math/armstrong_number.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,79 +4,116 @@
* number](https://en.wikipedia.org/wiki/Narcissistic_number) in decimal system.
*
* @details
* Armstrong number or [Narcissistic
* number](https://en.wikipedia.org/wiki/Narcissistic_number) is a number that
* is the sum of its own digits raised to the power of the number of digits.
* An Armstrong number (also known as a pluperfect digital invariant (PPDI) or
* narcissistic number) is a number that is the sum of its own digits each
* raised to the power of the number of digits.
*
* let n be the narcissistic number,
* \f[F_b(n) = \sum_{i=0}^{k-1}d_{i}^{k}\f] for
* \f$ b > 1 F_b : \N \to \N \f$ where
* \f$ k = \lfloor log_b n\rfloor is the number of digits in the number in base
* \f$b\f$, and \f$ d_i = \frac{n mod b^{i+1} - n mod b^{i}}{b^{i}} \f$
* For example:
* - \f$153 = 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153\f$
* - \f$1634 = 1^4 + 6^4 + 3^4 + 4^4 = 1 + 1296 + 81 + 256 = 1634\f$
*
* @author [Neeraj Cherkara](https://github.com/iamnambiar)
* @author [Akhila Pynam](https://github.com/akhila-pynam)
*/

#include <cassert> /// for assert
#include <cmath> /// for std::pow
#include <cstdint> /// for std::uint64_t
#include <iostream> /// for IO operations

/**
* @brief Function to calculate the total number of digits in the number.
* @param num Number
* @return Total number of digits.
* @namespace math
* @brief Mathematical algorithms
*/
namespace math {

/**
* @brief Computes base raised to the power of exponent using integer
* arithmetic.
* @param base The base number.
* @param exp The exponent.
* @return base raised to the power of exp.
*/
uint64_t power(uint64_t base, uint64_t exp) {
uint64_t res = 1;
while (exp > 0) {
if (exp & 1) {
res *= base;
}
base *= base;
exp >>= 1;
}
return res;
}

/**
* @brief Function to calculate the total number of digits in a number.
* @param num The number to count digits for.
* @return Total number of digits in the given number.
*/
int number_of_digits(int num) {
int total_digits = 0;
uint64_t number_of_digits(uint64_t num) {
if (num == 0) {
return 1;
}
uint64_t total_digits = 0;
while (num > 0) {
num = num / 10;
num /= 10;
++total_digits;
}
return total_digits;
}

/**
* @brief Function to check whether the number is armstrong number or not.
* @param number to be checked
* @return `true` if the number is armstrong.
* @return `false` if the number is not armstrong.
* @brief Function to check whether a number is an Armstrong number or not.
* @param number The number to be checked.
* @return `true` if the number is an Armstrong number.
* @return `false` if the number is not an Armstrong number.
*/
bool is_armstrong(int number) {
// If the number is less than 0, then it is not an armstrong number.
if (number < 0) {
return false;
}
bool is_armstrong(uint64_t number) {
uint64_t total_digits = number_of_digits(number);
uint64_t sum = 0;
uint64_t temp = number;

int sum = 0;
int temp = number;
// Finding the total number of digits in the number
int total_digits = number_of_digits(number);
while (temp > 0) {
int rem = temp % 10;
// Finding each digit raised to the power total digit and add it to the
// total sum
sum += static_cast<int>(std::pow(rem, total_digits));
temp = temp / 10;
uint64_t rem = temp % 10;
sum += power(rem, total_digits);
temp /= 10;
}

return number == sum;
}

} // namespace math

/**
* @brief Self-test implementations
* @returns void
*/
static void test() {
// is_armstrong(370) returns true.
assert(is_armstrong(370) == true);
// is_armstrong(225) returns false.
assert(is_armstrong(225) == false);
// is_armstrong(-23) returns false.
assert(is_armstrong(-23) == false);
// is_armstrong(153) returns true.
assert(is_armstrong(153) == true);
// is_armstrong(0) returns true.
assert(is_armstrong(0) == true);
// is_armstrong(12) returns false.
assert(is_armstrong(12) == false);
// 0 is an Armstrong number: 0^1 = 0
assert(math::is_armstrong(0) == true);

// Single-digit numbers are all Armstrong numbers: d^1 = d
assert(math::is_armstrong(1) == true);
assert(math::is_armstrong(5) == true);
assert(math::is_armstrong(9) == true);

// 2-digit numbers are never Armstrong numbers in base 10
assert(math::is_armstrong(10) == false);
assert(math::is_armstrong(12) == false);

// 3-digit Armstrong numbers: 153, 370, 371, 407
assert(math::is_armstrong(153) == true);
assert(math::is_armstrong(370) == true);
assert(math::is_armstrong(371) == true);
assert(math::is_armstrong(407) == true);
assert(math::is_armstrong(225) == false);
assert(math::is_armstrong(500) == false);

// 4-digit Armstrong numbers: 1634, 8208, 9474
assert(math::is_armstrong(1634) == true);
assert(math::is_armstrong(8208) == true);
assert(math::is_armstrong(9474) == true);
assert(math::is_armstrong(9475) == false);

std::cout << "All tests have successfully passed!\n";
}
Expand Down