THE PUZZLET PAGE

PUZZLET 035 - THE SOLUTION

' Puzzlet #035.
' Find an integer which can be divided by
' any n from 1 to 16 and always leave the
' remainder n - 1.
' By Dave Ellis.


declare PrintResult()
def flag1, flag2: int
def numerator, denominator, remainder: int
numerator = 31
flag1 = 0
openconsole
print
"Searching ..."

do
    ' outer loop controls numerator
    denominator = 16
    flag2 = 0
    do
        ' inner loop controls denominator
        remainder = numerator % denominator
        if remainder = denominator - 1
            denominator = denominator - 1
        else
            flag2 = 1
        endif
    until
flag2 | denominator < 2
    if denominator < 2
        flag1 = 1
    else
        numerator = numerator + 16
    endif
until
flag1

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

           
sub PrintResult
' pretty printer
def i: int
print
for
i = 1 to 16
    print ltrim$(str$(numerator)) + "/",
    print i,
    if i < 10
        print " ",
    endif
    print
"= ",
    print using ("######", int(numerator/i)),
    print " remainder ",
    print using ("##",i - 1)
next i
return

   

PROGRAM NOTES

We need to find a start value for the numerator before a seach can commence.  It has to be at least 15, so that dividing by 16 will leave a remainder of 16 - 1 , that is, 15. However, it's obvious that dividing 15 by 15 won't leave a remainder of 15 - 1 = 14.  Therefore the start value can't be 15.

The next possible start value is 31, which when divided by 16, still leaves a remainder of 15.  As you can see, this is still no good since it doesn't leave a remainder of 14 when divided by 15.  At this point, it becomes clear that it's best just to pick an arbitrarily low (but legal) start point and let the code do the rest.

Thus, we can safely initialise variable numerator to value 31 in the outer DO loop.  If you run your eye down to the end of that loop, you'll notice that the increment value for numerator is 16.  That ensures that it has a chance of success, since it will always be one less than a multiple of 16, and also makes the program run 16 times faster than it would numerator were to increment by one every time around the loop.

Before jumping into the inner DO loop, denominator is set to value 16.
This is because there are more likely to be failures to meet the requirement for higher values, so we keep run time lower by starting at 16. The inner loop executes
remainder = numerator % denominator on the current values held in these two variables.  The percentage sign denotes modular arithmetic, meaning that only the remainder is kept, stored, appropriately in variable remainder.

If remainder is equal to denominator minus 1, at least part of the requirement is met.  In these circumstances, denominator can be decremented by one and the test repeated.  This goes on until either all values for denominator down to 2 have been tried, or the test failed (indicated by use of variable flag2).  There's no need to use value 1 for denominator since it will always leave the required remainder of 0.

On exiting the inner DO loop, denominator is tested.  If it has successfully decremented right down to value 1 (even though that value wasn't actually tested), we must have found the solution. Variable flag1 is used in this situation to record success by setting it to value 1.  Otherwise numerator is incremented by 16 as described above, and the search continues.

Eventually, flag1 will be set and the program prints out the answer and stops. Shown below is a screen dump of the result.  If you're curious enough to look for more solutions by continuing the search, you'll be able to find plenty - but they're all multiples of 720719!

  Searching ...

  720719/1   = 720719  remainder   0
  720719/2   = 360359  remainder   1
  720719/3   = 240239  remainder   2
  720719/4   = 180179  remainder   3
  720719/5   = 144143  remainder   4
  720719/6   = 120119  remainder   5
  720719/7   = 102959  remainder   6
  720719/8   =  90089   remainder   7
  720719/9   =  80079   remainder   8
  720719/10 =  72071   remainder   9
  720719/11 =  65519   remainder 10
  720719/12 =  60059   remainder 11
  720719/13 =  55439   remainder 12
  720719/14 =  51479   remainder 13
  720719/15 =  48047   remainder 14
  720719/16 =  45044   remainder 15

  Press a key to exit ...

          


MAIN MENU
DOWNLOAD CODE
ARCHIVES

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