THE PUZZLET PAGE


How_Does_It_Work


FUNCTION:  FinalDigitProduct().  This function takes each of its argument's digits and finds their product.  If the product comprises two or more digits, the process is repeated on that product.  Eventually either zero or a single digit will result, and this is returned to the calling routine.

It's up to you what data type you make the argument, depending on the type of integer you want to process.


Type

Exponent of 2
Value

int 230 1073741824
uint 231 2147483648
int64 261 2305843009213693952
uint64 262 4611686018427387904

Declaring the function must be done like this:

declare FinalDigitProduct(p: int) (or whatever integer type you want).

Here's the code:


' +++ Subroutines and Functions +++

sub FinalDigitProduct(f)
' Multiplies the digits of argument f
' together. If the result is greater
' than ten, the process is repeated
' as many times as necessary to pro-
' duce a single digit result, which
' is then returned to the calling
' routine.
' By Dave Ellis.
def prod: int
do
    prod = 1
    do
        prod = prod*(f % 10)
        f = f/10
    until f = 0
    f = prod
until prod < 10
return prod

In order to make the code description easier to follow, I've numbered the lines:

1
2
3
4
5
6
7
8
9

do
    prod = 1
    do
        prod = prod*(f % 10)
       
f = f/10b
    until f = 0
    f = prod
until prod < 10
return prod

Now for an exegesis of the code, using the line numbering.

1

do.  Opens the main, outer do-until loop.

2

prod = 1.  The variable prod will be used to totalise the product of all the digits, building up one at a time.  If it were initialised to zero, the product would always be zero.  If it were initilised to a value exceeding 1, the product would be too large.  Therefore  it is initialised here to 1.

3

do.  This opens an inner, nested do-until loop.  All the real work of the function is done within it.

4

prod = prod*(f % 10).  Integer arithmetic is used to continue.  f % 10 means "divide f by 10 and discard everything in the answer except any remainder."  For example, if f contained 217, f % 10 would yield 7.

So we can paraphrase line 4 as: "Divide the contents of variable f by 10.  Multiply any remainder by the contents of variable prod, and save the result in prod, over-writing whatever was already stored in there."

5

f = f/10.  Integer arithmetic is used here again.  Because variable f was declared as in integer with the function, any division's remainder will be discarded.  So if contained 429, f % 10 would yield 42.

The important effect here is that the LSD (Least Signifant Digit) has been discarded or "chopped off."  When the loop is executed again, f will now be only 42 instead of 429, and the remainder after division by 10 in line 4 will be 2.

6

until f = 0. Now the loop's end has been reached, and a decision is needed: execute it again, or move on to the next piece of code? Line 6 makes this depend on the value stored in variable f.

Remember, f's LSD was chopped off in line 5.  If it is now zero, that must mean that all digits have been successively processed and then discarded, and there's no more to do.  So line 6 effectively says "If the value stored in variable f is zero, exit the do-until loop, otherwise execute it again."    Here's an example showing how an input of, say, 4291 would be handled.

f
f % 10
prod
f/1
4291
1
1
429
429
9
9
42
42
2
18
4
4
4
72
0
0





7

f = prod.  Having exited the inner do-until loop, the outer one can continue from where it left off to enter the inner loop.  When the inner loop is exited, f has done its job and now contains zero.  It will now be used again in the outer loop.  Whatever value is currently stored in variable prod is now loaded into f.

8

until prod < 10.  Now the code has reached the end of the outer loop, and, once again, a decision must be made about exiting or not.  This is made to depend on the value of prod.  If it's less than 10, the function has done its job, reducing the individual digit products of its argument to a single digit.

In such a case, no more needs to be done, so the code moves on.  Otherwise, it goes around the outer do-until loop again.  So line 8 is saying "If the value stored in variable prod is less than 10, quit the do-until loop, otherwise go around and execute it again."

The inset flowchart sums all this up, with the upper (inner) loop nested within the lower (outer) loop.

Final_Digit_Product_Flowchart

9

return prod.  The function has completed its task, and all that now remains is to return the result to the calling routine.  The function has totalised the result into variable prod, so this is what must be returned.


MAIN MENU
HOW DOES IT WORK?

Site design/maintenance: Dave Ellis E-mail me!
Last Updated: January 31st, 2010.