Teaser 3333: Hey, diddle, diddle …
From The Sunday Times, 9th August 2026 [link] [link]
Kat and Fidel each held an investment bond. They were over the moon when these matured with different four-digit values (whole numbers of dollars). Unfortunately, a fraction (equivalent to under ten per cent, and the same for both bonds) was deducted as fees, leaving four-digit whole-number nett values. “Fees, what a diddle!” complained Kat. Fidel agreed, adding that in another sense each maturity value was a DIDDLE. Kat was puzzled. Fidel explained that a DIDDLE was a whole number with Different Increasing Digits (left to right) that is DivisibLe Exactly by each digit.
Later, walking his little dog, Fidel stopped at Withespoon’s “Prancing Cow” pub, where he told his friend, Dishran, these things, but no values. Dishran, an accountant, knew the “fees” fraction and calculated the values with certainty.
Find the nett values.
[teaser3333]
Jim Randell 7:03 am on 9 August 2026 Permalink |
This Python program runs in 72ms. (Internal runtime is 1.6ms).
from enigma import (defaultdict, irange, subsets, nconcat, fraction, printf) # generate possible k-digit DIDDLEs def generate(k): # consider 4 different increasing digits for ds in subsets(irange(1, 9), size=k, select='C'): # form the number n = nconcat(ds) # check it is divisible by each of the digits if not all(n % d == 0 for d in ds): continue # return the number yield n # group (gross, net) values by fee (as a fraction) d = defaultdict(list) # consider possible 4-digit DIDDLEs (= maturity values) for G in generate(4): # consider possible 4-digit net values for N in irange(G - 1, 1000, step=-1): # calculate fees (as a fraction) (a, b) = fraction(G - N, G) # must be less than 10% if not (10 * a < b): break d[(a, b)].append((G, N)) # look for a fraction that gives exactly 2 values for ((a, b), vs) in d.items(): if len(vs) == 2: printf("fees = {a}/{b} -> vs = {vs}")Solution: [To Be Revealed]
LikeLike
Ruud 8:08 am on 9 August 2026 Permalink |
import peek import istr import collections collect = collections.defaultdict(list) for gross in istr.range(length=4): if gross.is_increasing() and all(gross.divided_by(c) for c in gross): for fraction in range(11, int(gross)): if gross.is_divisible_by(fraction): collect[fraction].append(gross) for fraction, grosses in collect.items(): if len(grosses) == 2: peek(fraction) for gross in grosses: nett = gross - gross // fraction peek(nett, gross)LikeLike
Ruud 8:12 am on 9 August 2026 Permalink |
`divided_by` could also read `is_divisible_by` which is arguably a bit more clear.
LikeLike
Frits 12:45 pm on 9 August 2026 Permalink |
I didn’t want to publish a similar solution.
from math import gcd from itertools import combinations from functools import reduce d2n = lambda s: reduce(lambda x, y: 10 * x + y, s) # 4-digit maturity values for Kat and Fidel mvs = [mv for c in combinations(range(1, 10), 4) if all((mv := d2n(c)) % dgt == 0 for dgt in c)] # assume (minimal) fraction is a / b then k % b = 0 and f % b = 0 # collect all valid denominators <b> that can be factors of <k> and <f> for b in {gcd(k, f) for k, f in combinations(mvs, 2)}: # check all fractions a / b for a in range(1, b): nett = [v - dm[0] for v in mvs if (dm := divmod(a * v, b))[1] == 0 and dm[0] <= v // 10] if len(nett) == 2: print("answer:", nett)LikeLike