' 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:
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.