Teaser 3327: Water, water everywhere
From The Sunday Times, 28th June 2026 [link] [link]
Having moved to the southern coast of a large lake, George and Martha have acquired a speedboat, capable of doing V km/h. They are going to visit their daughter who lives 60 km due north on the opposite shore of the lake. A steady current is flowing from the West due East. George has told Martha that he intends to propel the boat at top speed at such an angle that it will complete the direct south-north journey in T minutes.
“In that case”, replied Martha confidently, “you have allowed for the current to be flowing at C km/h, reducing your speed by exactly 1 or 2 km/h to S“.
C, V, S and T are all two-digit whole numbers, with S+T being a perfect power.
How fast is the current flowing?
[teaser3327]







Jim Randell 6:59 am on 28 June 2026 Permalink |
This is a straightforward solution that starts by considering possible V values.
The following Python program runs in 72ms. (Internal runtime is 223µs).
from enigma import (irange, div, is_ipower, ircs, printf) # consider possible 2-digit speeds (= V) for V in irange(10, 99): # the speed is reduced by 1 or 2 to give S for S in (V - 1, V - 2): if S < 10: continue # the 60 km journey at effective speed S takes T min T = div(3600, S) if T is None or T < 10 or T > 99: continue # speed of the current (= C) C = ircs(V, -S) if C is None or C < 10 or C > 99: continue # S+T is a perfect power if not is_ipower(S + T): continue # output solution printf("C={C} [V={V} S={S} T={T}]")Solution: [To Be Revealed]
LikeLike
Jim Randell 7:50 am on 28 June 2026 Permalink |
A (slightly shorter, and faster) alternative approach (that assumes C < S).
The internal runtime of this program is 90µs.
from enigma import (pythagorean_triples, div, is_ipower, printf) # consider possible C, S, V speeds for (C, S, V) in pythagorean_triples(99): if C < 10 or (V - S) not in {1, 2}: continue # calculate time for the 60 km journey at effective speed S (= T min) T = div(3600, S) if T is None or T < 10 or T > 99: continue # S+T is a perfect power if not is_ipower(S + T): continue # output solution printf("C={C} [V={V} S={S} T={T}]")LikeLiked by 1 person
Ruud 11:37 am on 28 June 2026 Permalink |
I wonder how you know that S+T can only by a number to the power of 2..6.
I think it would be more accurate to test for the irange of 2..int(math.log2(S + T), which happens to be 6 for all your tested values of S + T .
LikeLike
Jim Randell 11:59 am on 28 June 2026 Permalink |
@Ruud: 2^7 (= 128) is greater than 2-digits, so a 2 digit number cannot be a power greater than 6.
But S + T is the sum of two 2-digit numbers, so we should check powers up to 2^7.
However I already have [[
is_ipower()]] in enigma.py to check if a number is an exact power, so I switched to using that.LikeLike
Ruud 12:06 pm on 28 June 2026 Permalink |
I don’t think that’s the reason. S+T does not have to be 2 digits long (and in fact it isn’t).
You are actually testing for 123, 120 and 125! So there must be another reason how you now that it can’t be >= 128.
LikeLike
Jim Randell 1:28 pm on 28 June 2026 Permalink |
It might be more efficient to set up a collection of possible powers, and then check if S + T is in it:
# generate possible powers pows = first(ipowers(), skip=lt(20), count=lt(199), fn=set) # or use a precomputed set pows = {25, 27, 32, 36, 49, 64, 81, 100, 121, 125, 128, 144, 169, 196}Using the precomputed set brings my second program down to 82µs.
LikeLike
Ruud 8:22 am on 28 June 2026 Permalink |
import peek import istr import math for s in istr.range(length=2): t = istr.divided_by(3600, s, 0) if len(t) == 2 and any((t + s).is_power_of(n) for n in range(2, int(math.log2(t + s) + 1))): for v in (s + 1, min(s + 2, 100)): c = istr(math.sqrt(v * v - s * s)) if c * c == v * v - s * s and len(c) == 2: peek(c, v, s, t)LikeLike
ruudvanderham 11:11 am on 28 June 2026 Permalink |
With the latest istr, we can do:
import peek import istr import math for s in istr.divisors(3600): if len(s) == 2: t = istr.divided_by(3600, s) if len(t) == 2 and (t + s).is_power_of(): for v in (s + 1, min(s + 2, 100)): c = istr(math.sqrt(c2 := v * v - s * s)) if c * c == c2 and len(c) == 2: peek(c, v, s, t) elif len(s) > 2: breakLikeLike