DEV Community

José Oscátegui
José Oscátegui

Posted on

Narcissistic number

A Narcissistic Number is a number that is the sum of its own digits, each one raised to the power of the number of digits.

Example: 1^3 + 5^3 + 3^3 = 1 + 125 + 27 = 153

To practice! :D

Top comments (11)

Collapse
 
pbouillon profile image
Pierre Bouillon • Edited

Here is a little implementation in Python3.6:

def is_narcissistic(nb: int) -> bool:
    return nb == sum([int(c)**len(str(nb)) for c in str(nb)])


if __name__ == '__main__':
    print([nb for nb in range(10000) if is_narcissistic(nb)])

Display:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407, 1634, 8208, 9474]
Collapse
 
ganeshtata profile image
Tata Ganesh • Edited

Awesome answer, Pierre!
I have one doubt though. Wouldn't it be better to first convert nb into a string, and then just pass the string to the list comprehension, instead of doing str(nb) for every iteration? That is,

str_nb = str(nb)
return nb == sum(int(c)**len(str_nb) for c in str_nb)

This might be a little more efficient. Also, we can remove the list comprehension inside and replace it with a generator.

Collapse
 
vandersluispe profile image
Paul van der Sluis • Edited

This is fun! Here is a Python 3.5 one-liner with only one calculation of the length of nb per nb :

print([nb for nb in range(10000) if nb == sum(int(c)**l for l in [len(str(nb))] for c in str(nb))])

And now with also one conversion of str(nb) per nb:

print([nb for nb in range(10000) if nb == sum(int(c)**l for str_nb in [str(nb)] for l in [len(str_nb)] for c in str_nb)])

Collapse
 
pbouillon profile image
Pierre Bouillon

Yeah you're right! Thank you, that's clever!

Collapse
 
kip13 profile image
kip • Edited

I'm learning Rust and this challenge looks good to practice, this is my solution.

fn main() {
  for number in 0..1000 {
    if is_narcissistic(number) {
      println!("{} is narcissistic", number);
    }
  }
}

fn is_narcissistic(number: i32) -> bool {
  digits_pow(number) == number
}

fn digits_pow(mut number: i32) -> i32 {
  let digits= (number as f64).log10()
    .floor() + 1_f64;

  let mut sum = 0;

  while number != 0 {
    sum += ((number % 10)).pow(digits as u32);
    number = ((number / 10) as f64).floor() as i32;
  }

  sum
}
0 is narcissistic
1 is narcissistic
2 is narcissistic
3 is narcissistic
4 is narcissistic
5 is narcissistic
6 is narcissistic
7 is narcissistic
8 is narcissistic
9 is narcissistic
153 is narcissistic
370 is narcissistic
371 is narcissistic
407 is narcissistic
Collapse
 
kepta profile image
Kushan Joshi

Here's my little code golf in javascript.

const digit_pow = (n, pow = n.toString().length, sum = 0) =>
  n ? digit_pow(Math.floor(n / 10), pow, sum + (n % 10) ** pow) : sum;

for (let i = 0; i < 1e6; i++) {
  if (digit_pow(i) === i) console.log(i);
}
Collapse
 
jay profile image
Jay

My Rust solution.

fn is_narc(n: i32) -> bool {
  let digits = n.to_string().len() as u32;
  let mut sum = 0;
  let mut m = n;
  while m != 0 {
    sum += (m % 10).pow(digits);
    m /= 10;
  }
  sum == n
}

// Usage
fn main() {
  (0..=1_000_000)         // upto 1 million
    .filter(|&x| is_narc(x))
    .for_each(|x| println!("{}", x));
}
Collapse
 
kip13 profile image
kip • Edited

Good solution!!, but if you test the code here doesnt run, only works in a more updated version no ? What version do you use ?

Collapse
 
jay profile image
Jay

The inclusive range (..=) that I've used is available from Rust 1.24. It will work with previous versions. But you can change it from (0..=1_000_000) to (0..1_000_001) and it should work in any previous version.

repl.it uses Rust 1.9, the for_each method for iterator is avalable from 1.21 onwards. You can save the filtered list and call for loop on elements.

Here's the repl.it link with formatted code, that will work over there. link

If you want to run the newer version, here's a link to rust playground with the code.

Have fun 😃

Collapse
 
kspeakman profile image
Kasey Speakman • Edited

An Elm Solution

Algorithm

narcSum digits sum todo =
  if todo == 0 then
    sum
  else
    narcSum digits ((todo % 10) ^ digits + sum) (todo // 10)

isNarc a =
  a == narcSum (String.length (toString a)) 0 a

Usage

List.range 0 1000000
  |> List.filter isNarc

Results

Here are the narcissists up to 10 billion.

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 24678050 24678051 88593477 146511208 472335975 534494836 912985153 4679307774

Collapse
 
drgaud profile image
DrGaud

Dont know if this is still up for discussion but here is my code snippet in JS hope it helps...


function narcissist(num){
  const entry = String(num).split('');
  const getPow = entry
                 .map((value)=> Math.pow(value,entry.length));
  const getAccValue = getPow.reduce((acc,curr) => acc + curr);
  return getAccValue === num ? getAccValue : false;
}

console.log(narcissist(153))