THE PUZZLET PAGE

PUZZLET 038 - THE SOLUTION

' Puzzlet #038
' Find a 5-digit integer whose value
' is equal to the sum of the factorials
' of its own digits.
' By Dave Ellis.


declare SumFactorials(s: int)
declare Factorial (f: int)
declare PrintResult()
def flag, n, sumFact: int
openconsole
print
"Searching ...": print
n = 10000
flag = 0

do
    sumFact = SumFactorials(n)
    if sumFact = n
        flag = 1
    else
        n = n + 1
    endif
until
flag

PrintResult()
print: print "Press a key to exit ..."   
do: until inkey$ <> ""
closeconsole
end


sub SumFactorials(s)
' returns the sum of the factorials of
' the individual digits of s

def i, num, sum: int
num = s
sum = 0
for i = 1 to 5
    sum = sum + Factorial(num % 10)
    num = int(num/10)
next i
return sum

sub Factorial(f)
' returns the factorial of f
def it, fact: int
fact = 1
for it = 1 to f
    fact = fact*it
next it
return fact

sub PrintResult
' pretty printer
def i, digit: int
def n$: string
print "Answer: ", n: print
n$ = str$(n)
for i = 2 to 6
    digit = val(mid$(n$, i, 1))
    print mid$(n$,i,1) + "! = ",
    print using ("########", Factorial(digit))
next i
print: print "Sum: ",
print using ("########", n)
return


PROGRAM NOTES

Once again, this program can best be understood by looking at the main routine, since top-down programming has been used.  For ease of description, it's shown below with line numbers.

 1
 2
 3
 4
 5
 6
 7
 8
do
    sumFact = SumFactorials(n)
    if sumFact = n
        flag = 1
    else
        n = n + 1
    endif
until
flag


In the setup, variable flag was set to 0 (FALSE), and variable n set to 1000, the loweset possible 5-digit value. Everything else necessary is included in the DO loop between lines 1 and 8.  

Line 2: variable n is passed to the function SumFactorials(), whose task is to totalise the factorials of the individual digits of its argument. When this is returned, it's stored in variable sumFact.

Line 3:  the value just stored in sumFact is compared with n.  

Line 4: if they're equal, we have a solution, and flag is set to 1 (TRUE) to signal this.  In such a case, the program moves to line 8, and seeing flag true, exits the DO loop.

Lines 5 and 6: if n and sumFact aren't equal, n is incremented ready for another try.  Note that flag is unchanged for this action.

Lines 7 and 8: The decision-making if-else-endif process is over, and the program needs to make a decision: should it execute the DO loop again, or exit it?  A quick look at flag is all that's needed.  If it's still false, go round again, otherwise exit the loop.

The two functions called by the main routine, SumFactorials() and Factorial(), are very simple. The latter is created to service the former, and is only called from there, not from the main routine.

Factorial() takes every value from 1 to argument f and multiplies them together using variable it in a for-next loop. The ever-increasing product is stored in variable fact and, when the for-next loop is exited, fact's value is passed back to the calling routine.

Note that Factorial() will return a value of 1 when the argument is 0. This is because 0! = 1.  If you haven't come across this before, here's an explanation.

Consider the expression 4!/4.  This equates to (1x2x3x4)/4 = 6.  But 6 is 3!  So we could complete the expression as 4!/4 = 3!  You can see that, whatever value is used on the left-hand side of the equation, the right-hand side will be equal to the factorial of one less than that value. Generalising, n!/n = (n-1)! Now substitute value 1 into the equation.  1!/1 = (1-1)!, or, 0! = 1.  Neat, isn't it?


SumFactorials() uses variable i to work through argument s.  At each loop it calls function Factorial() to obtain the factorial of the LSD (least-significant, or rightmost, digit) of s and adds this into variable sum. The LSD is found by the expression (num % 10), which performs an integer division on num and only keeps any remainder - the LSD.

Each time around the loop num's LSD is discarded by the expression
num = int(num/10). This ensures that, next time around the loop, the LSD will be 1 position to the left of that chosen last time.

After 5 iterations the sum of the factorials of all of s's digits are stored in sum.  sum is then passed that back to the main routine.


When you run the code,  it produces the inset screen.

The answer relies on the fact that the factorial of zero is one, that is,  0! = 1. See program notes for an explantion.

Searching ...

Answer: 40585

4! =       24
0! =        1
5! =      120
8! =    40320
5! =      120

Sum:    40585

Press any key to exit ...

          

          


MAIN MENU
DOWNLOAD CODE
ARCHIVES

Site design/maintenance: Dave Ellis E-mail me!
Last Updated: February 22nd, 2004.