Tags

, , , , , , , , ,

Finally, I pulled my finger out of somewhere and wrote some Java code to calculate all Narcissistic Numbers. I ran it for numbers up to 9 digits and it took about 30 minutes in total. The time taken will increase exponentially, the more digits you run it for.

I’m sure you code/number buffs out there could write a more elegant solution to the problem – please let me know if you do.

Here’s a sample of the output from this code;

DIGITS: 3
153
370
371
407
DIGITS: 4
1634
8208
9474
DIGITS: 5
54748
92727
93084
DIGITS: 6
548834
DIGITS: 7
1741725
4210818
9800817
9926315
DIGITS: 8
24678050
24678051
88593477
DONE.

Or if you decide to run this, let me know how far you got. Here is the breakdown of the code, followed by the full class for you to copy/paste.

Let’s use some math libraries to make the job easier:

import java.math.BigDecimal;  // We need this class for the correct level of precision
import java.math.MathContext; // This class is used to by BigDecimal methods to determine precision

We define the starting and ending number of digits to process:

public class NarcissismItself {

	static final int LO_RANGE = 3;  // From this number of digits...
	static final int HI_RANGE = 8;  // ...to this number of digits.
	// Maximum 39. No Narcissistic numbers from 40 digits. Mathematical fact.
	// After 9, it can take a long time to run.

	static final int CHAR0 = Integer.valueOf((char)'0');  // Used later to calculate char/int conversion offset

The outer loop iterates through the numbers of digits we wish to process:

	public static void main(String[] args) {

		Integer iDigits = LO_RANGE;
		do {                                       // Iterate through the required numbers of digits
			iterateNarcissisticNumbers(iDigits);
			iDigits++;
		} while (iDigits <= HI_RANGE);

		System.out.println("DONE.");

	}

We work out the start and ending number for the number of digits in the current iteration:

	private static void iterateNarcissisticNumbers(Integer iDigits) {

		System.out.print("DIGITS: ");
		System.out.print(iDigits);
		System.out.println();

		// Calculate starting number, based on digits e.g. 7 digits = 1000000
		BigDecimal bdLo = new BigDecimal(10).pow(iDigits-1, new MathContext(40));
		// Calculate ending number, based on digits e.g. 7 digits = 9999999
		BigDecimal bdHi = new BigDecimal(10).pow(iDigits, new MathContext(40)).subtract(new BigDecimal(1));
		bdLo.setScale(0); // No decimals
		bdHi.setScale(0); // No decimals
		
		// Check all numbers between starting and ending numbers
		checkNarcissisticNumber(bdLo, bdHi, iDigits);
		
	}

We iterate through each number in the range and check whether each is Narcissistic:

	private static void checkNarcissisticNumber(BigDecimal bdLo, BigDecimal bdHi, int iDigits) {

		BigDecimal bdLoop = bdLo.subtract(new BigDecimal(1));
		do {                                                   // For all candidate numbers, check whether Narcissistic
			bdLoop = bdLoop.add(new BigDecimal(1));
			check1NarcissisticNumber(bdLoop, iDigits);
		} while ((bdLoop.compareTo(bdHi) == -1));

	}

Here’s the code that checks an individual number for Narcissism:

	private static void check1NarcissisticNumber(BigDecimal bdNumber, int iDigits) {

		BigDecimal accumulation = new BigDecimal(0);

		for (char sX : bdNumber.toPlainString().toCharArray()) {  // Iterate through all digits
			int charVal = Integer.valueOf(sX)-CHAR0;              // Convert char to int
			BigDecimal accum = new BigDecimal(charVal).pow(iDigits,new MathContext(40)); // Raise to power based on digits
			accumulation = accumulation.add(accum);               // Add to accumulated figure
		}

		if (bdNumber.compareTo(accumulation) == 0) {    // Is the accumulated number the same as the original number?
			System.out.print(bdNumber.toPlainString()); // Yes? Then it is Narcissistic.
			System.out.println();
		}
	
	}

Finally, we close off the class code block:

}

The full class is here in its entirety:

import java.math.BigDecimal;  // We need this class for the correct level of precision
import java.math.MathContext; // This class is used to by BigDecimal methods to determine precision

public class NarcissismItself {

	static final int LO_RANGE = 3;  // From this number of digits...
	static final int HI_RANGE = 8;  // ...to this number of digits.
	// Maximum 39. No Narcissistic numbers from 40 digits. Mathematical fact.
	// After 9, it can take a long time to run.

	static final int CHAR0 = Integer.valueOf((char)'0');  // Used later to calculate char/int conversion offset

	//--------------------------------------
	public static void main(String[] args) {

		Integer iDigits = LO_RANGE;
		do {                                       // Iterate through the required numbers of digits
			iterateNarcissisticNumbers(iDigits);
			iDigits++;
		} while (iDigits <= HI_RANGE);

		System.out.println("DONE.");

	}

	//---------------------------------------------------------------
	private static void iterateNarcissisticNumbers(Integer iDigits) {

		System.out.print("DIGITS: ");
		System.out.print(iDigits);
		System.out.println();

		// Calculate starting number, based on digits e.g. 7 digits = 1000000
		BigDecimal bdLo = new BigDecimal(10).pow(iDigits-1, new MathContext(40));
		// Calculate ending number, based on digits e.g. 7 digits = 9999999
		BigDecimal bdHi = new BigDecimal(10).pow(iDigits, new MathContext(40)).subtract(new BigDecimal(1));
		bdLo.setScale(0); // No decimals
		bdHi.setScale(0); // No decimals
		
		// Check all numbers between starting and ending numbers
		checkNarcissisticNumber(bdLo, bdHi, iDigits);
		
	}

	//------------------------------------------------------------------------------------------
	private static void checkNarcissisticNumber(BigDecimal bdLo, BigDecimal bdHi, int iDigits) {

		BigDecimal bdLoop = bdLo.subtract(new BigDecimal(1));
		do {                                                   // For all candidate numbers, check whether Narcissistic
			bdLoop = bdLoop.add(new BigDecimal(1));
			check1NarcissisticNumber(bdLoop, iDigits);
		} while ((bdLoop.compareTo(bdHi) == -1));

	}

	//------------------------------------------------------------------------------
	private static void check1NarcissisticNumber(BigDecimal bdNumber, int iDigits) {

		BigDecimal accumulation = new BigDecimal(0);

		for (char sX : bdNumber.toPlainString().toCharArray()) {  // Iterate through all digits
			int charVal = Integer.valueOf(sX)-CHAR0;              // Convert char to int
			BigDecimal accum = new BigDecimal(charVal).pow(iDigits,new MathContext(40)); // Raise to power based on digits
			accumulation = accumulation.add(accum);               // Add to accumulated figure
		}

		if (bdNumber.compareTo(accumulation) == 0) {    // Is the accumulated number the same as the original number?
			System.out.print(bdNumber.toPlainString()); // Yes? Then it is Narcissistic.
			System.out.println();
		}
	
	}

}
Advertisements