From The Sunday Times, 16th July 1978 [link]
Recently a hot-drink vending machine was installed in our office. Very nice it is too — completely up to date it was when it was bought. There are five switches, a slot for your money, and a button. The switches are labelled TEA, COFFEE, CHOCOLATE, MILK and SUGAR, and you select the combination you want, put in your money, press the button, and out comes your drink. Why, you can even have coffolatea if you want!
At least, this is the idea. Unfortunately, during the ten years it has been in store, “awaiting approval”, mice have chewed up the wiring. Mice with soldering irons, I should think. The result is now that no switch affects its “own” ingredient at all, but instead turns on two other ingredients, each ingredient being turned on by two different switches. However, if two switches are set which turn on the same ingredient, then they cancel each other out, and that ingredient doesn’t come out at all.
The result is somewhat chaotic, though occasionally some of the output is actually drinkable. For instance, when you ask for white sweet coffee, you get unsweetened milky tea; when you ask for sweet milky chocolate, you get sweet chocolate without milk; and when you ask for unsweetened milky tea you get a glorious gooey mocha — i.e. chocolate and coffee with milk and sugar.
Luckily, pressing the “deliver” button reinstates the original chaos, so that setting the same switches always gives the same results.
So, what is the easiest way to get white coffee without sugar? (i.e. Name the fewest switches that will deliver just coffee and milk).
This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980). The puzzle text above is taken from the book.
[teaser884]
Jim Randell 5:08 pm on 17 December 2021 Permalink |
This Python program finds the solution constructively. It runs in 52ms.
Run: [ @replit ]
from enigma import (Rational, irange, unzip, printf) Q = Rational() # look for solutions def solve(): # initial ages ages = [7, 0] # collect gifts (newest first) gifts = list(list(5 * x for x in irange(age, 1, step=-1)) for age in ages) totals = list(sum(x) for x in gifts) while True: # add in data for the next year for (i, _) in enumerate(ages): ages[i] += 1 v = 5 * ages[i] gifts[i].insert(0, v) totals[i] += v # consider missing years for ms in unzip(gifts): # calculate averages without missing year avgs = list(Q(t - m, a) for (t, m, a) in zip(totals, ms, ages)) # look for avgs[0] = 121% of avgs[1] if 100 * avgs[0] == 121 * avgs[1]: yield (ages, totals, ms) # find the first solution for (ages, totals, ms) in solve(): t = sum(totals) - sum(ms) printf("total = {t}; ages = {ages}; missing={ms}") breakSolution: The total of the gifts is £ 6660.
The daughters are currently aged 40 and 33, and the missing amounts are £ 140 and £ 105, when the daughters were 28 and 21.
In total the elder daughter has received £ 3960 (an average of £ 99 per year), and the younger has received £ 2700 (an average of £ 81 + 9/11 per year).
And we have:
Analytically we see that the £ 5 multiplier cancels out and we are looking for values of:
where: n is the age of the younger daughter, and k ∈ [1, n] is her age in the missing year.
This simplifies to:
And we can then just look for the first n that gives a viable value for k:
from enigma import (irange, inf, div, T, printf) # consider age of youngest daughter for n in irange(1, inf): # calculate missing year k = div(((3 * n - 76) * n - 479) * n, 6 * n + 242) if not (k is None or k < 0 or k > n): # output solution t1 = T(n) - k t2 = T(n + 7) - (k + 7) t = 5 * (t1 + t2) printf("[n={n} k={k}] total = {t}; ages = ({n+7}, {n})") breakFurther analysis shows that in order for k to be positive we require: n > (38 + √2881) / 3 ≈ 30.56.
And for k ≤ n we require: n ≤ 103/3 ≈ 34.33.
So we only need to check k ∈ [31, 34], which we can do manually.
LikeLike
GeoffR 9:12 am on 18 December 2021 Permalink |
LikeLike
NigelR 3:23 pm on 19 December 2021 Permalink |
apologies Jim – I haven’t worked out how to post code properly. Is there a guide somewhere, please?
acum,bcum=140,0 #140 is accumulated gifts for daughter 1 for birthdays 1-7 for y in range(8,90): #start from 1st birthday for daughter 2 acum+=5*y bcum+=5*(y-7) for i in range (8,y): #iterate over previous years to remove 1 year at a time if abs(((acum-5*i)/y)-1.21*((bcum-(5*(i-7)))/(y-7)))<0.0001: print("total gifted is:",(acum-5*i)+(bcum-5*(i-7)))LikeLike
Jim Randell 3:44 pm on 19 December 2021 Permalink |
Hi,
You can include code like this:
For longer programs (80 lines for more) you can also include the
collapse="true"parameter, to hide it until clicked on.Be careful though,it is not possible to edit a comment in WordPress once it is posted.
LikeLike
Tony Brooke-Taylor 7:31 am on 20 December 2021 Permalink |
With a bit of rearrangement of a formula for the ratio of averages you can pretty much solve this manually. Once you have the limits you can almost intuit the correct value for the younger daughter’s age but the program below loops until it finds a solution.
# Find real roots of a quadratic equation with conventional coefficients a, b, c def quad_roots(a, b, c): r = (b ** 2 - 4 * a * c) if r >= 0: low = (-b - r**(1/2))/2/a up = (-b + r**(1/2))/2/a return low, up # Define missing_year as the age of the younger daughter when the gift was missed # Make this the subject of the equation formed from taking the ratio of averages given # The lower bound for the younger age can be inferred from the condition that missing_year exceeds 0 low_lim = max([int(r) for r in quad_roots(3, -76, -479) if r > 0]) + 1 # The upper bound for the younger age can be inferred from the condition that it exceeds missing_year up_lim = max([int(r) for r in quad_roots(3, -(76 + 6), -(479 + 242)) if r > 0]) + 1 # Find the value for the age now of the younger daughter, such that missing_year is an integer for young_age, missing_year in ((n, (3 * n ** 2 - 76 * n - 479) / (6 * n + 242) * n) for n in range(low_lim, up_lim)): if missing_year % 1 == 0: total = 0 for d in [0, 7]: total += ((young_age + d) * ((young_age + d)+1)/2 - (missing_year + d)) print("Total given to both daughters is", total * 5) breakLikeLike