My solution to Project Euler Problem 30.
Here’s the problem:
Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits:
1634 = 14 + 64 + 34 + 44
8208 = 84 + 24 + 04 + 84
9474 = 94 + 44 + 74 + 44
As 1 = 14 is not a sum it is not included.
The sum of these numbers is 1634 + 8208 + 9474 = 19316.
Find the sum of all the numbers that can be written as the sum of fifth powers of their digits.
My Solution:
# Author: Will Clausen
# Date: 4/7/14
# Description: This file solves problem 30 for Project Euler
import math
# This function solves problem 30. Some noteworthy solution details include
# using a list to go through the set of possible numbers. I used a list
# because I wanted a way to easily obtain the next distinct permutation of
# numbers with digits in increasing order from left to right.
def problem30():
# Store the final sum in this variable
final = 0
# Start by checking 11, because the numbers 1 through 10 are clearly
# not going to meet the crtiteria of the problem.
check = [0, 0, 0, 0, 1, 1]
checkNum = listToNum(check)
# This loop condition is an artifact of how I increment the number I am
# checking (note that I check numbers in list form). Think of it as
# saying, "while the number being checked is within the known limit of
# possibilities"
while check[0] != 10:
# Get the sum of the fifth powers of the digits.
digitSum = sumOfDigits(check)
# Convert this sum into a list
digitSumList = numToList(digitSum)
helper = []
# Loop through the digits of the number being checked
# to determine if the number being checked can be permuted
# into its sum (in which case, we want to add that number to
# the final sum).
good = True
for i in range(len(check)):
if check[i] not in digitSumList:
good = False
break
digitSumList.remove(check[i])
if good:
final += digitSum
# Move to the next number
check = nextNum(check)
checkNum = listToNum(check)
return final
# This function takes in a number in list form (base 10) and increments it
# to the next number that has all its digits in increasing order from left to
# right.
def nextNum(numList):
# The list must have length greater than 0 for
# this function to make any sense
assert(len(numList) > 0)
# Start with the least significant digit, and work towards
# the bigger numbers
index = len(numList) - 1
# Increment the number
numList[index] += 1
# If this causes the number to equal 10, update accordingly
while numList[index] == 10:
# If the last spot in the number list is now at 10
# that means there is nowehere left to increment, so
# just terminate and return the messed up list
if index == 0:
break
# Move the index to the left 1
index -= 1
# Demonstrate that ten 1's is equal to one 10 and add
# accordingly.
numList[index] += 1
# Here's where things get weird. In the while loop above,
# note that some indices of numList will have tens in them
# here's where we make those numbers make sense. In the problem,
# it's not necessary to loop through every number, we only need to
# loop through distinct permutations of numbers with a certain number
# of digits. e.g. if we just checked 123, we have also checked
# 132, 231, 213, 312, 321. This loop ensures that we get a new DISTINCT
# number that we haven't checked before. It makes everything much faster.
for i in range(index, len(numList)):
numList[i] = numList[index]
return numList
# This function takes a number in list form, and converts it to integer form
def listToNum(numList):
# Start by taking the most significant digit
num = numList[0]
for i in range(1, len(numList)):
# This ensures that the most significant digit ends up in the right
# place.
num *= 10
# Add the proper digit in the proper spot
num += numList[i]
return num
# This function takes a number in integer form and converts it to list form.
def numToList(num):
# The easiest way to code this was to make the number a string...
strNum = str(num)
final = [0, 0, 0, 0, 0, 0]
# ... then loop through the string and convert the character back to an
# integer. I don't know if this is the most efficient way to do this,
# but it was the solution that came to mind most quickly.
for i in range(len(strNum)):
final[len(final) - i - 1] = int(strNum[len(strNum) - i - 1])
return final
# This function sums the fifth power of the digits in an input number
def sumOfDigits(numList):
final = 0
for i in range(0, len(numList)):
final += pow(numList[i], 5)
return final
# Run the program to determine the solution.
if __name__ == "__main__":
answer = problem30()
print "Answer: " + str(answer)