Narcissistic decimal number

From Rosetta Code
Revision as of 19:33, 7 March 2014 by rosettacode>Gerard Schildberger (→‎{{header|REXX}}: added REXX section header comments.)
Task
Narcissistic decimal number
You are encouraged to solve this task according to the task description, using any language you may know.

A Narcissistic decimal number is a positive decimal number, in which if there are digits in the number then the sum of all the individual digits of the number raised to the power is equal to .

For example, if is 153 then , the number of digits is 3 and we have and so 153 is a narcissistic decimal number.

The task is to generate and show here, the first 25 narcissistic numbers.

C

<lang c>#include <stdio.h>

typedef long long xint;

  1. define MAX_LEN 16

xint dpow[MAX_LEN + 1][11];

void init(void) { int i, p; for (p = 0; p <= MAX_LEN; p++) for (i = 0; i <= 10; i++) dpow[p][i] = p ? dpow[p-1][i] * i : 1; }

void narc(int power, int pos, xint value, xint dsum) { xint i, ds, v, ten;

if (!pos) { printf(" %lld", value); return; }

ten = dpow[pos - 1][10]; for (i = (pos == power); i < 10; i++) { ds = dsum + dpow[power][i]; v = value + i * ten;

if (ds >= v + ten) break;

if (v <= ds + dpow[power][9] * (pos - 1)) narc(power, pos - 1, v, ds); } }

int main(void) { int i; init();

for (i = 1; i <= 16; i++) { printf("length %d:", i); narc(i, i, 0, 0); putchar('\n'); }

return 0; }</lang>

Output:
length 1: 1 2 3 4 5 6 7 8 9
length 2:
length 3: 153 370 371 407
length 4: 1634 8208 9474
length 5: 54748 92727 93084
length 6: 548834
length 7: 1741725 4210818 9800817 9926315
length 8: 24678050 24678051 88593477
length 9: 146511208 472335975 534494836 912985153
^C

D

Simple Version

<lang d>void main() {

   import std.stdio, std.algorithm, std.conv, std.range;
   immutable isNarcissistic = (in uint n) pure =>
       n.text.map!(d => (d - '0') ^^ n.text.length).sum == n;
   writefln("%(%(%d %)\n%)",
            uint.max.iota.filter!isNarcissistic.take(25).chunks(5));

}</lang>

Output:
0 1 2 3 4
5 6 7 8 9
153 370 371 407 1634
8208 9474 54748 92727 93084
548834 1741725 4210818 9800817 9926315

Faster Version

<lang d>import std.stdio, std.algorithm, std.range, std.array;

uint[] narcissists(in uint m) pure nothrow {

   typeof(return) result;
   foreach (immutable uint digits; 0 .. 10) {
       const digitPowers = 10.iota.map!(i => i ^^ digits).array;
       foreach (immutable n; 10 ^^ (digits - 1) .. 10 ^^ digits) {
           uint div = n, digitPSum;
           while (div) {
               digitPSum += digitPowers[div % 10];
               div /= 10;
           }
           if (n == digitPSum) {
               result ~= n;
               if (result.length >= m)
                   return result;
           }
       }
   }
   assert(0);

}

void main() {

   writefln("%(%(%d %)\n%)", 25.narcissists.chunks(5));

}</lang> With LDC2 compiler prints the same output in less than 0.3 seconds.

Perl 6

Here is a straightforward, naive implementation. It works but takes ages. <lang perl6>sub is-narcissistic(Int $n) { $n == [+] $n.comb »**» $n.chars }

for 0 .. * {

   if .&is-narcissistic {

.say; last if ++state$ >= 25;

   }

}</lang>

Output:
0
1
2
3
4
5
6
7
8
9
153
370
371
407
Ctrl-C

Here the program was interrupted but if you're patient enough you'll see all the 25 numbers.

Python

This solution pre-computes the powers once.

<lang python>from __future__ import print_function from itertools import count, islice

def narcissists():

   for digits in count(0):
       digitpowers = [i**digits for i in range(10)]
       for n in range(int(10**(digits-1)), 10**digits):
           div, digitpsum = n, 0
           while div:
               div, mod = divmod(div, 10)
               digitpsum += digitpowers[mod]
           if n == digitpsum:
               yield n

for i, n in enumerate(islice(narcissists(), 25), 1):

   print(n, end=' ')
   if i % 5 == 0: print() 

print()</lang>

Output:
0 1 2 3 4 
5 6 7 8 9 
153 370 371 407 1634 
8208 9474 54748 92727 93084 
548834 1741725 4210818 9800817 9926315

REXX

This is an idiomatic approach.

version 1

<lang rexx>/*REXX program to generate and display a number of narcissistic numbers.*/ numeric digits 39 /*be able to handle the largest #*/ parse arg N .; if N== then N=25 /*get number of narcissistic #'s.*/ N=min(N,89) /*there are 89 narcissistic #s.*/

  1. =0 /*number of narcissistic # so far*/
    do j=1  until #==N;  L=length(j)  /*get the length of the J number.*/
    s=left(j,1)**L                    /*1st digit in J raised to L pow.*/
             do k=2  for L-1          /*perform for each digit in  J.  */
             s=s+substr(j,k,1)**L     /*add digit raised to pow to sum.*/
             if s>j  then iterate j   /*perform a short-circuit test.  */
             end   /*k*/              /* [↑]  calculate the rest of sum*/
    if s\==j  then iterate            /*does sum equal to  J?   No ∙∙∙ */
    #=#+1                             /*bump the narcissistic num count*/
    say right(#,9) ' narcissistic:' j /*display index & narcissistic #.*/
    end   /*j*/                       /* [↑]    this list starts at 1. */
                                      /*stick a fork in it, we're done.*/</lang>

output   when using the default input:

        1  narcissistic: 1
        2  narcissistic: 2
        3  narcissistic: 3
        4  narcissistic: 4
        5  narcissistic: 5
        6  narcissistic: 6
        7  narcissistic: 7
        8  narcissistic: 8
        9  narcissistic: 9
       10  narcissistic: 153
       11  narcissistic: 370
       12  narcissistic: 371
       13  narcissistic: 407
       14  narcissistic: 1634
       15  narcissistic: 8208
       16  narcissistic: 9474
       17  narcissistic: 54748
       18  narcissistic: 92727
       19  narcissistic: 93084
       20  narcissistic: 548834
       21  narcissistic: 1741725
       22  narcissistic: 4210818
       23  narcissistic: 9800817
       24  narcissistic: 9926315
       25  narcissistic: 24678050

version 2

This REXX version is optimized to pre-compute all the ten (single) digits raised to all possible powers (which is 39). <lang rexx>/*REXX program to generate and display a number of narcissistic numbers.*/ numeric digits 39 /*be able to handle the largest #*/ parse arg N .; if N== then N=25 /*get number of narcissistic #'s.*/ N=min(N,89) /*there are 89 narcissistic #s.*/

  do w=1  for 39                      /*generate tables: digits ^ L pow*/
    do i=0  for 10;  @.w.i=i**w;  end /*build table of 10 digs ^ L pow.*/
  end   /*w*/                         /* [↑]  table is of a fixed size.*/
  1. =0 /*number of narcissistic # so far*/
    do j=1  until #==N;  L=length(j)  /*get the length of the J number.*/
    s=0                               /*sum of the J digs ^ L  (so far)*/
             do k=1  for L            /*perform for each digit in  J.  */
             _=substr(j,k,1)          /*select a single digit to sum.  */
             s=s+@.L._                /*add digit raised to pow to sum.*/
             if s>j  then iterate j   /*perform a short-circuit test.  */
             end   /*k*/              /* [↑]  calculate the rest of sum*/
    if s\==j  then iterate            /*does sum equal to  J?   No ∙∙∙ */
    #=#+1                             /*bump the narcissistic num count*/
    say right(#,9) ' narcissistic:' j /*display index & narcissistic #.*/
    end   /*j*/                       /* [↑]    this list starts at 1. */
                                      /*stick a fork in it, we're done.*/</lang>

output   is the same as REXX version 1.