Here is a functional approach:
Narciss[x_] := With[{num = IntegerDigits[x]}, Total[num^Length[num]] == x]
Here is a compiled version of the above function:
NarcissC = Compile[{{x, _Integer}},
With[{num = IntegerDigits[x]}, Total[num^Length[num]] == x],
Parallelization -> True, CompilationTarget -> "C",
RuntimeAttributes -> Listable, RuntimeOptions -> "Speed"]
Now you can do something like
AbsoluteTiming[Position[NarcissC[Range[10000000]], True] // Flatten]
{1.003214, {1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208,
9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817,
9926315}}
to get all the m-Narcissistic numbers from 1 to 10000000.
For a further bump in speed as suggested by chyaong, here is NarcissC2
(Using Sum
instead of Total
)
NarcissC2 = Compile[{{x, _Integer}},
With[{num = IntegerDigits[x]}, Sum[i^Length@num, {i, num}] - x],
CompilationTarget -> "C", RuntimeAttributes -> Listable, RuntimeOptions-> "Speed"];
Now you can do:
Pick[#, NarcissC2[#], 0] &@Range[10000000] // AbsoluteTiming
Which gives:
{0.475276, {1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208,
9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315}}
EDIT
It turns out that you can get a bump using Total
and Pick
instead of Position
(not as fast as Sum
):
NarcissC1 = Compile[{{x, _Integer}},
With[{num = IntegerDigits[x]}, Total[num^Length[num]] - x], Parallelization -> True,
CompilationTarget -> "C", RuntimeAttributes -> Listable, RuntimeOptions -> "Speed"]
Then
Pick[#, NarcissC1[#], 0] &@Range[10000000] // AbsoluteTiming
gives:
{0.626322, {1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208,
9474, 54748, 92727, 93084, 548834, 1741725, 4210818, 9800817, 9926315}}