Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find all narcissistic (armstrong) numbers faster on Java

Is there more efficient way to do that? Given number N - find all the narcissistic ( armstrong ) numbers that < N. Here is my code, but I guess there is more efficient solutions. Also, probably, we could solve it through bit operation?

public static void main(String args[]) throws  Exception
 {
    long a = System.nanoTime();
    int t [] = getNumbers(4_483_647L);
    long b = System.nanoTime();
    System.out.println("Time totally "+(b-a));
    for(int k: t)
        System.out.print(k+" ");
}
public static int[] getNumbers(long N)
{

    int length=1;
    int porog=10, r=1, s=1;
    double k;
    LinkedList<Integer> list = new LinkedList<>();

    for(int i=1; i<N; i++)
    {
        if(i==porog)
        {
            length++;
            porog*=10;
        }
        s = i;
        k=0;
        while(s>0)
        {
            r = s%10;
            k+=Math.pow(r, length);
            if(k>i)break;
            s=s/10;
        }
        if((int)k==i)
            list.add(i);
    }
   int[] result  = new int[list.size()];
    int i=0;
    for(int n: list)
    {
        result[i] = n;
        i++;
    }

    return result;  }  }
like image 446
kurumkan Avatar asked Dec 03 '25 13:12

kurumkan


2 Answers

Some observations:

  • If your initial maximum is a long, your results should be long types, too, just in case (int works for you as the narcissistic numbers are far apart)
  • If you change your return type to be a "big" Long, you can use Collections.toArray() to repack the results to an array...
  • ...although really, you should just return the linked list...
  • You don't need to keep recalculating powers. For each decade in the outer loop, you only ever need i^j, where i=0..9 and j is the number of digits in the current decade
  • In fact, you don't need Math.pow() at all, as you can just use multiplication at each decade

Applying my ideas from my comment above and also changing the method signature, you get something that runs about 30 times faster:

public static Long[] getNumbers(long N) {
    int porog = 10;
    LinkedList<Long> list = new LinkedList<>();
    // initial powers for the number 0-9
    long[] powers = { 0l, 1l, 2l, 3l, 4l, 5l, 6l, 7l, 8l, 9l };

    for (long i = 1; i < N; i++) {
        if (i == porog) {
            porog *= 10;
            // calculate i^length
            for (int pi = 1; pi < 10; pi++) {
                powers[pi] *= pi;
            }
        }
        long s = i;
        long k = 0;
        while (s > 0) {
            int r = (int)(s % 10);
            k += powers[r];
            if (k > i)
                break;
            s /= 10;
        }

        if (k == i)
            list.add(i);
    }

    return list.toArray(new Long[]{});
}
like image 189
dovetalk Avatar answered Dec 05 '25 03:12

dovetalk


From Rosetta Code blog (not my own code)

public static boolean isNarc(long x){
    if(x < 0) return false;

    String xStr = Long.toString(x);
    int m = xStr.length();
    long sum = 0;

    for(char c : xStr.toCharArray()){
        sum += Math.pow(Character.digit(c, 10), m);
    }
    return sum == x;
}
like image 25
wiredniko Avatar answered Dec 05 '25 03:12

wiredniko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!