THE PUZZLET PAGE

PUZZLET 068 - THE SOLUTION


' Puzzlet #068
' A tank can be filled from any of three
' taps.  Each tap takes an exact  number
' of minutes,  between 900 and 1,000, to
' fill the tank on its own. If all three
' are on at the same time the tank still
' fills  in an exact number of  minutes.
' Find each tap's fill time and the tot-
' al fill time.
' By Dave Ellis.

declare GetTotalFlow()
declare PrintResult()
def pipe1, pipe2, pipe3: int
def totalFlow: double
openconsole
print "Calculating ...": print
print "#01  #02  #03  Tot": print

for pipe1 = 900 to 998
    for pipe2 = pipe1 + 1 to 999
        for pipe3 = pipe2 + 1 to 1000
            GetTotalFlow
            if totalFlow = int(totalFlow)
                PrintResult()
            endif
        next pipe3
    next pipe2
next pipe1

print: print "No More!"
print
: print "Press a key to exit... ",
do: until inkey$ <> ""
closeconsole
end


sub
GetTotalFlow
' calculates the total flow produced by
' pipe1, pipe2, and pipe3 simultaneously
' for their current flow rates.
def recTotalFlow: double
recTotalFlow = 1/pipe1 + 1/pipe2 + 1/pipe3
totalFlow = 1/recTotalFlow
return

sub PrintResult
' pretty printer
print pipe1,
print " ", pipe2,
print " ", pipe3,
print " ", totalFlow
return

 
   
PROGRAM NOTES


The main perquisite to solving this problem is to understand the "total flow" concept.  Since water flowing through taps is analagous to current flowing through resistors, we can turn to electrical engineering for assistance.

Current flowing through resistors in parallel is calculated as:


Formula

That is, the total resistance is equal to the reciprocal of the sum of the reciprocals of every resistor.  As an aside, you may be interested to know that, in the special case of just two resistors in parallel, the formula simplifies to the famous "product over sum" equation.

Let's see how this important formula is applied in the code.  We begin by generating every possible combination of the three pipe flows, held in variables pipe1, pipe2, and pipe3 with the following lines:

for pipe1 = 900 to 998
    for pipe2 = pipe1 + 1 to 999
        for pipe3 = pipe2 + 1 to 1000


For each of the combinations, the total flow is calculated by calling the subroutine GetTotalFlow(), which essentially consists of just three lines of code:

def recTotalFlow: double
recTotalFlow = 1/pipe1 + 1/pipe2 + 1/pipe3
totalFlow = 1/recTotalFlow


You can see how the total resistance formual quoted above has been adapted here to do the job.  The reciprocal of the total flow is stored in variable recTotalFlow.  Once we have it, the reciprocal is taken to give the actual flow and the result stored in variable totalFlow, ready to be picked up by the main routine.  Note that recTotalFlow and totalFlow  are of type double to ensure any decimal places are retained.

All we need to do now is to ask "Is this result an integer?" If it is, we have a valid solution.  This final task is accomplished by these lines:

if totalFlow = int(totalFlow)
    PrintResult()


Note the uyse of
double
typing in the code when decimals are being dealt with.  This is because we are likely to be dealing with very close results here, such as 929.00000001 etc.  An ordinary float type may not pick this up, as there are less places of precision.

When you run the program, it generates the inset screen. 

As you can see, there are four solutions in total. 


Calculating ...

#01  #02  #03  Tot

900  936  975  312
903  924  946  308
903  946  990  315
930  960  992  320


No more!

Press any key ..



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