說明
在n位的整數中,若加總每個數字的n次方後等於該整數,該整數稱為阿姆斯壯數 (Armstrong number),又稱自戀數(Narcissistic number)(因為各數字n次方後加總又等於本身,感覺很自戀?)。 例如153可以滿足13 + 53 + 33 = 153,153就是個阿 姆斯壯數,阿姆斯壯數有88個,最大為39位數的 115132219018763992565095597973971522401,已證實超過39位數不存在阿姆斯壯數。解法
阿姆斯壯數的尋找,基本上是在問如何將一個數字分解為個位數、十位數、百位數......,這 只要使用除法與餘數運算就可以了,例如要找出所有三位數阿姆斯壯數。輸 入input為n位數,則可如下分解出位數:個
位 (input / 100) % 10
十位 (input / 101) % 10
百 位 (input / 102) % 10
...
n 位 (input / 10n-1) % 10
      
      十位 (input / 101) % 10
百 位 (input / 102) % 10
...
n 位 (input / 10n-1) % 10
底下列出的實作僅逐一列舉數字並判斷是否為阿姆斯壯數,位數大時求解時間會急劇拉長。可改進的方法之一:
- 對於同樣為n位數而言,數字的n次方重複運算是不必要的,這部份可先製表而後直接查表並進行加總(像是Java實 作中的例子)。
- 進行數字裁剪,將同為n位數的數劃分為數個集合,將尋找阿姆斯壯數縮剪為尋找包括阿姆斯壯數的集合。例如3位數 中,122、212、221會屬於同一集合(因此需要搭配快速排列組合),詢問此集合是否包括13 + 23 + 23 = 17則答案為否(因而需要搭配有序集合以快速確認是否包括),而135、315、153屬於同一集合,詢 問此集合是否包括13 + 33 + 53 = 153則答案為是,則153為阿姆斯壯數,在位數多時,可藉由集合裁剪掉大量單獨數字加總後測試的需求,從而加快求解速 度。
 實作:C    Java  
 Python    Scala   
      Ruby    JavaScript   
      Haskell
      
      
      #include <stdio.h> 
#include <stdlib.h> 
int isNarcissistic(double);
void narcissistic(double*, int);
int main(void) { 
    double armstrongs[88] = {0};
    narcissistic(armstrongs, 3);
    int i;
    for(i = 0; armstrongs[i] != 0; i++) {
        printf("%.0f\n", armstrongs[i]);
    }
    return 0; 
} 
int isNarcissistic(double number) {
    int digits[39] = {0};
    double num = number;
    int i;
    for(i = 0; num != 0; i++) {
        digits[i] = (int) num % 10;
        num = (int) (num / 10);
    }
    double sum = 0.0;
    int j;
    for(j = 0; j <= i; j++) {
        sum += pow(digits[j], i);
    }
    return sum == number;
}
void narcissistic(double* armstrongs , int n) {
    double bound = pow(10, n < 40 ? n : 39);
    double i;
    int j;
    for(i = 0, j = 0; i < bound; i++) if(isNarcissistic(i)) {
        armstrongs[j] = i; j++;
    }
}
import java.math.BigInteger;
import java.util.*;
import static java.lang.Math.*;
public class Armstrong {
    private static double[][] pows;
    
    public static List<Double> narcissistic(int n) {
        pows = new double[n + 1][];
        pows[1] = new double[] {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
        for(int i = 2; i <= n; i++) {
            pows[i] = new double[] {
                0, 1, pows[i - 1][2] * 2, pows[i - 1][3] * 3, 
                pows[i - 1][4] * 4, pows[i - 1][5] * 5, 
                pows[i - 1][6] * 6, pows[i - 1][7] * 7, 
                pows[i - 1][8] * 8, pows[i - 1][9] * 9
            };
        }
    
        List<Double> armstrongs = new ArrayList<>();
        double bound = pow(10, n < 40 ? n : 39);
        for(double i = 1; i < bound; i++) if(isNarcissistic(i)) {
            armstrongs.add(i);
        }
        return armstrongs;
    }
    
    public static boolean isNarcissistic(double number) {
        List<Integer> digits = new ArrayList<>();
        double num = number;
        while(num != 0) {
            digits.add((int) num  % 10);
            num = floor(num / 10);
        }
        double sum = 0;
        for(Integer d : digits) {
            sum += pows[digits.size()][d];
        }
        return sum == number;
    }
    
    public static void main(String[] args) {
        for(Double d : narcissistic(7)) {
            System.out.printf("%.0f%n", d);
        }
    }
}from functools import reduce
def toDigits(num):
    return [] if num == 0 else ([num % 10] + toDigits(num // 10))
def isNarcissistic(number):
    digits = toDigits(number)
    return reduce(lambda sum, d: sum + d ** len(digits), 
               digits, 0) == number
def narcissistic(n):
    return [i for i in range(1, 10 ** (n if n < 40 else 39)) 
                  if isNarcissistic(i)]
print(narcissistic(3))
import scala.math.BigInt
import scala.math.pow
def toDigits(num: BigInt): List[Int] = {
    if(num == 0) Nil else (num % 10).toInt :: toDigits(num / 10)
}
def isNarcissistic(number: BigInt) = {
    val digits = toDigits(number)
    (0 /: digits) { (sum, d) => sum + pow(d, digits.size).toInt } == number
}
def narcissistic(n: Int) = {
    for(i <- BigInt(1) until BigInt(10).pow(if(n < 40) n else 39)
        if isNarcissistic(i)) yield i
}
narcissistic(3).foreach(println _)def toDigits(num)
    num == 0 ? [] : ([num % 10]) + toDigits(num / 10)
end
def isNarcissistic(number)
    digits = toDigits(number)
    digits.reduce(0) {|sum, d| sum + d ** digits.size} == number
end
def narcissistic(n)
    (1...10 ** (n < 40 ? n : 39)).select {|i| isNarcissistic(i)}
end
print(narcissistic(3))
function isNarcissistic(number) {
    var digits = [];
    var num = number;
    while(num != 0) {
        digits.push(num  % 10);
        num = parseInt(num / 10);
    }
    var sum = 0;
    for(var i = 0; i < digits.length; i++) {
        sum += Math.pow(digits[i], digits.length);
    }
    return sum == number;
}
    
function narcissistic(n) {
    var armstrongs = [];
    var bound = Math.pow(10, n < 40 ? n : 39);
    for(var i = 1; i < bound; i++) if(isNarcissistic(i)) {
        armstrongs.push(i);
    }
    return armstrongs;
}
print(narcissistic(3));
toDigits num =
    if num == 0 then [] else (num `mod` 10) : toDigits (num `div` 10)
isNarcissistic number = 
    number == (foldl (\sum d -> sum + d ^ (length digits)) 0 digits)
    where digits = toDigits number
narcissistic n =
    [i | i <- [1..10 ^ (if n < 40 then n else 39)], isNarcissistic(i)]
main = print \$ narcissistic 3

