Optimizing code – Part 4
The next mini optimization we can do is to bail out earlier because when summing the number and we overshoot the original then we can stop immediately. For example 9 ** 6 is a big number and so with bigger numbers it makes sense to bail out earlier.
import sys
from datetime import datetime
POWERS = [0,1,2,3,4,5,6,7,8,9]
LENGTH = 1
def recalculate_powers() -> None:
global POWERS
for i,v in enumerate(POWERS):
POWERS[i] = i * v
def is_narcissistic(x: int) -> bool:
global LENGTH, POWERS
org = x
digits = []
total = 0
while x > 0:
_, x = digits.append(x % 10), x // 10
cur_length = len(digits)
if cur_length != LENGTH:
LENGTH = cur_length
recalculate_powers()
for i in digits:
total += POWERS[i]
if total > org:
return False
return total == org
def find_narcissistic_numbers(desired: int) -> None:
for x in range(1,sys.maxsize):
if is_narcissistic(x):
desired -= 1
if desired == 0:
return
start = datetime.utcnow()
find_narcissistic_numbers(28)
print(datetime.utcnow() - start)
The time for this code to run on my laptop is: 0:06:21.202479
To compare this to the original run of the naive implementation is, which was 0:08:09.315972. Even on my slow hardware, it still resulted in a speed up of about 25%.