Armstrong Number

C

Solution 1

/**
 * Solution 1.
 *
 * Use a few helper functions to decompose the int into
 * an array of its digits so we can sum each digit and compare with
 * the input number.
 */

#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include "armstrong_numbers.h"

#define MAX_DIGITS 12

/**
 * Counts the number of digits in `n`.
 *
 * ASSUME: `n` is positive.
 */
size_t count_digits(long int n) {
  short len = 1;
  long int d = n;

  while (d >= 10) {
    d = d / 10;
    ++len;
  }

  return len;
}

/**
 * Turns the int into an array of its composing int digits.
 */
short* to_digits(long int n, size_t *len) {
  *len = count_digits(n);
  short *digits = malloc(sizeof(short) * (*len) + 24);
  short i = (*len) - 1;
  long int d = n;

  while (d >= 10) {
    *(digits + i--) = d % 10;
    d = d / 10;
  }

  *digits = d;

  return digits;
}

bool is_armstrong_number(int n) {
  size_t len = count_digits(n);
  short *digits = to_digits(n, &len);
  long int sum = 0;

  for (size_t i = 0; i < len; ++i)
    sum += pow(*(digits + i), len);

  free(digits);

  return sum == n;
}

Solution 2

/**
 * Solution 2.
 *
 * No helper functions and compute the power using an inner for loop.
 *
 * Get the number of digits by using the log10(n) + 1 math trick.
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
#include "armstrong_numbers.h"

#define MAX_DIGITS 12

bool is_armstrong_number(int n) {
  int len = log10(n) + 1,
      total = 0,
      pow_tmp = 1,
      d = n,
      r;

  if (d < 10) return 1;

  while (d > 0) {
    r = d % 10;

    pow_tmp = 1;

    for (int i = 0; i < len; ++i)
      pow_tmp *= r;

    total += pow_tmp;

    r = d % 10;
    d = d / 10;
  }

  return total == n;
}