Teaser 3028: Rainbow numeration
From The Sunday Times, 4th October 2020 [link] [link]
Dai had seven standard dice, one in each colour of the rainbow (ROYGBIV). Throwing them simultaneously, flukily, each possible score (1 to 6) showed uppermost. Lining up the dice three ways, Dai made three different seven-digit numbers: the smallest possible, the largest possible, and the “rainbow” (ROYGBIV) value. He noticed that, comparing any two numbers, only the central digit was the same, and also that each number had just one single-digit prime factor (a different prime for each of the three numbers).
Hiding the dice from his sister Di’s view, he told her what he’d done and what he’d noticed, and asked her to guess the “rainbow” number digits in ROYGBIV order. Luckily guessing the red and orange dice scores correctly, she then calculated the others unambiguously.
What score was on the indigo die?
I’ve changed the wording of the puzzle slightly to make it clearer.
[teaser3028]
Jim Randell 5:17 pm on 2 October 2020 Permalink |
(Note: I’ve updated my program (and the puzzle text) in light of the comment by Frits below).
This Python program runs in 49ms.
Run: [ @repl.it ]
from enigma import irange, subsets, nconcat, filter_unique, printf # single digit prime divisor def sdpd(n): ps = list(p for p in (2, 3, 5, 7) if n % p == 0) return (ps[0] if len(ps) == 1 else None) # if flag = 0, check all values are the same # if flag = 1, check all values are different check = lambda flag, vs: len(set(vs)) == (len(vs) if flag else 1) # all 6 digits are represented digits = list(irange(1, 6)) # but one of them is repeated ans = set() for (i, d) in enumerate(digits): ds = list(digits) ds.insert(i, d) # make the smallest and largest numbers smallest = nconcat(ds) p1 = sdpd(smallest) if p1 is None: continue largest = nconcat(ds[::-1]) p2 = sdpd(largest) if p2 is None or p2 == p1: continue printf("smallest = {smallest} ({p1}); largest = {largest} ({p2})") # find possible "rainbow" numbers rs = list() for s in subsets(ds[:3] + ds[4:], size=len, select="P", fn=list): s.insert(3, ds[3]) # rainbow has only the central digit in common with smallest and largest if not all(check(i != 3, vs) for (i, vs) in enumerate(zip(s, ds, ds[::-1]))): continue rainbow = nconcat(s) p3 = sdpd(rainbow) if p3 is None or not check(1, (p1, p2, p3)): continue rs.append(tuple(s)) # find rainbow numbers unique by first 2 digits for rainbow in filter_unique(rs, (lambda s: s[:2])).unique: n = nconcat(rainbow) printf("-> rainbow = {n} ({p3})", p3=sdpd(n)) # record the indigo value ans.add(rainbow[5]) # output solution printf("indigo = {ans}")Solution: The score on the indigo die is 4.
Each of the digits 1-6 is used once, and there is an extra copy of one of them. So there is only one possible set of 7 digits used.
The smallest number is: 1234456 (divisible by 2).
And the largest number is: 6544321 (divisibly by 7).
There are 17 possible values for the “rainbow” number, but only 3 of them are uniquely identified by the first 2 digits: 2314645, 3124645, 3614245 (and each is divisible by 5).
The scores on the green, indigo and violet dice are the same for all three possible “rainbow” numbers: 4, 4, 5. So this gives us our answer.
LikeLike
Frits 11:02 pm on 2 October 2020 Permalink |
“each number had just one prime factor under 10 (different for each number)”.
The three numbers you report seem to have same prime factors under 10, maybe I have misunderstood.
LikeLike
Jim Randell 11:10 pm on 2 October 2020 Permalink |
@Frits: I think you could be right. I took it to mean that it wasn’t the same prime in each case (two of the numbers I originally found share a prime). But requiring there to be three different primes does also give a unique answer to the puzzle (different from my original solution). So it could well be the correct interpretation (and it would explain why we weren’t asked to give the rainbow number). Thanks.
LikeLike
Frits 11:35 pm on 2 October 2020 Permalink |
@Jim: I hope to publish my program tomorrow (for three different prime numbers). I don’t have a clean program yet.
Your solution also seems to be independent of the indigo question (it could have been asked for another colour). In my solution this specific colour is vital for the solution.
LikeLike
Frits 11:26 am on 3 October 2020 Permalink |
Next time I try to use the insert function (list).
from enigma import factor, irange, concat, peek from itertools import permutations as perm from collections import defaultdict P = {2, 3, 5, 7} # number of same characters at same positions nr_common = lambda x, y: sum(1 for i, a in enumerate(x) if a == y[i]) # prime factors under 10 factund10 = lambda x: [p for p in P if int(x) % p == 0] # if list contains one entry then return possible values at position i charvals = lambda s, i: {x[0][i] for x in s if len(x) == 1} n = 6 digits = concat([x for x in irange(1, n)]) # for each digit i occuring twice in lowest and highest number for i in irange(1, n): str_i = str(i) # build lowest and highest number low = digits[:i] + str_i + digits[i:] hgh = low[::-1] # get prime factors under 10 u10low = factund10(low) u10hgh = factund10(hgh) # each number with one prime factor under 10 (different for each number) if len(u10low) != 1 or len(u10hgh) != 1 or u10low[0] == u10hgh[0]: continue rainbow = defaultdict(list) # for this combination of lowest and highest check the rainbow possibilities for pe in perm(low[:n//2] + low[n//2 + 1:]): # weave central digit into permutation pe at center position rb = concat(pe[:n//2] + tuple(low[n//2]) + pe[n//2:]) # check rainbow number on only the central digit being the same if nr_common(rb, low) != 1 or nr_common(rb, hgh) != 1: continue u10rb = factund10(int(rb)) # all three prime factors under 10 are different if len(u10rb) == 1 and u10rb[0] != u10low[0] and u10rb[0] != u10hgh[0]: # store rainbow number with as key first 2 digits rainbow[rb[:2]].append(rb) # if first 2 digits rainbow number is unique then list indigo values indigo = charvals(rainbow.values(), 5) if len(indigo) == 1: print(f"The score on the indigo die: {peek(indigo)}")LikeLike
Frits 2:58 pm on 4 October 2020 Permalink |
A more efficient program (without explaining the choices as this is a new puzzle).
from enigma import factor, irange, concat, diff from itertools import permutations as perm from collections import defaultdict # number of same characters at same positions nr_common = lambda x, y: sum(1 for i, a in enumerate(x) if a == y[i]) # prime factors under 10 factund10 = lambda x: [p for p in {2, 5, 7} if int(x) % p == 0] # if list contains one entry then return possible values at position i charvals = lambda s, i: {x[0][i] for x in s if len(x) == 1} n = 6 digits = concat([x for x in irange(1, n)]) # for each digit i occuring twice in lowest and highest number for i in irange(1, n): if i % 3 == 0: continue # build lowest and highest number low = digits[:i] + str(i) + digits[i:] hgh = low[::-1] # get prime factors under 10 u10low = factund10(low) u10hgh = factund10(hgh) if len(u10hgh) != 1 or u10hgh[0] != 7: continue # each number with one prime factor under 10 (different for each number) if len(u10low) != 1: continue rainbow = defaultdict(list) # for this combination of lowest and highest check the rainbow possibilities center = str(i) remaining = diff(low[:n//2] + low[n//2 + 1:], "5") # try possibilities for first digit for d1 in diff(remaining, "1" + str(n)): # find values for positions without the edges and the center for pe2 in perm(diff(remaining, d1) , n - 2): # build rainbow number rb = d1 + concat(pe2[:(n-1)//2]) + center + \ concat(pe2[(n-1)//2:]) + "5" if int(rb) % u10hgh[0] == 0: continue # check rainbow number on only the central digit being the same if nr_common(rb, low) != 1 or nr_common(rb, hgh) != 1: continue # store rainbow number with as key first 2 digits rainbow[rb[:2]].append(rb) # if first 2 digits rainbow number is unique then list indigo values indigo = charvals(rainbow.values(), 5) if len(indigo) == 1: print(f"The score on the indigo die: {indigo.pop()}")LikeLike