Teaser 3198: The sixth element
From The Sunday Times, 7th January 2024 [link] [link]
Agent J discovered that S.P.A.M.’s IQ booster drug comprises five elements with atomic numbers Z under 92. Some information had been coded as follows: Z1[4;6], Z2[1;4], Z3[4;6], Z4[0;6] and Z5[7;2], where Z5 is lowest and Z3 is highest. Code key: [Remainder after dividing Z by 8; Total number of factors of Z (including 1 and Z). The drug’s name is the elements’ chemical symbols concatenated in encoded list order.
J subsequently discovered the Z3 and Z5 values. Now MI6 had just fifteen possible sets of atomic numbers to consider. Finally, J sent a sixth element’s prime Z value (a catalyst in the drug’s production, not part of it). She’d heard it was below Z1 and above Z2, without knowing these. MI6 boffins were now sure of the drug’s name.
Give the catalyst’s atomic number.
[teaser3198]
Jim Randell 5:05 pm on 5 January 2024 Permalink |
This Python program checks that the six Z numbers are all different (although this is not explicitly stated in the puzzle text, but it seems like a reasonable additional requirement).
It runs in 55ms. (Internal runtime is 711µs).
Run: [ @replit ]
from enigma import ( defaultdict, irange, tau, group, cproduct, primes, singleton, printf ) # map Z numbers to code code = lambda z: (z % 8, tau(z)) # group Z numbers by code g = group(irange(1, 91), by=code) # choose a sequence from the given codes codes = [(4, 6), (1, 4), (4, 6), (0, 6), (7, 2)] # collect possible sequences by (z3, z5) values d = defaultdict(list) for (z1, z2, z3, z4, z5) in cproduct(g[k] for k in codes): if len({z1, z2, z3, z4, z5}) != 5: continue # z5 is the lowest if not (z5 < min(z1, z2, z3, z4)): continue # z3 is the highest if not (z3 > max(z1, z2, z4, z5)): continue d[(z3, z5)].append((z1, z2, z3, z4, z5)) # knowing z3 and z5 gives 15 possible sequences for (k, vs) in d.items(): if len(vs) != 15: continue # consider possible prime z6 values for z6 in primes.between(1, 91): # look for matching sequences check = lambda z1, z2, z3, z4, z5: z2 < z6 < z1 and z6 != z4 zs = singleton(zs for zs in vs if check(*zs)) if zs is None: continue # output solution printf("z6={z6} -> zs={zs}")Solution: The catalyst has atomic number 47.
The constituent elements (Z1..Z5) have atomic numbers: 52, 33, 68, 32, 7.
So, the name of the drug is: TEASERGEN (= Te As Er Ge N).
And the catalyst (Z6) has atomic number 47 (= Ag (Silver)).
LikeLike
NigelR 12:48 pm on 7 January 2024 Permalink |
A bit convoluted but it seems to work!!
from itertools import product def is_prime(n): if (n % 2 == 0 and n > 2) or n < 2: return False for i in range(3, int(n**0.5) + 1, 2): if n % i == 0: return False return True factno = lambda n: len([i for i in range(1, n + 1) if n % i == 0]) zvals = lambda a,b: [i for i in range(1,92) if i%8 == a and factno(i) == b] #Code values for z1 - z5 Z = [[4,6], [1,4], [4,6], [0,6], [7,2]] #create dictionary d with lists of possible values for each element d = {i:zvals(x[0],x[1]) for i,x in enumerate(Z,1)} #create cand as list with valid sets of element values cand = [] for x in (dict(zip(d.keys(), values)) for values in product(*d.values())): #z3 is highest, z5 is lowest and 5 different elements if x[3] != max(vals:= x.values()) or len(set(vals)) != 5 or x[5] != min(vals): continue else: cand.append(x) #remove duplicates and create list of valid x3 & x5 z3z5 = [list(tupl) for tupl in {tuple(item) for item in [[x[3],x[5]] for x in cand]}] #Find z3z5 entry that has 15 possible sets res = [x for x in z3z5 if len([y for y in cand if y[3]==x[0] and y[5]==x[1]])==15 ] if len(res)>1 : print('unique solution not found') exit() else: res = res[0] #flatten res to list of selected x3 & x5 #strip invalid sets from cand cand = [x for x in cand if x[3]==res[0] and x[5]==res[1]] z6lst=[] #look for possible prime values of z6 between z2 and z1 for x in cand: if x[2]>x[1]:continue for y in range(x[2]+1,x[1]): if is_prime(y): z6lst.append([y,x]) z6set = [x[0] for x in z6lst] #look for singleton value of z6 z6 = [x for x in z6set if z6set.count(x)==1] if len(z6)==1: z6 = z6[0] else: print('unique solution not found') exit() soltn = [x for x in z6lst if x[0]==z6][0] print(f'Catalyst atomic number was {soltn[0]}.') outstr = 'Z' + ' Z'.join([str(i)+' = '+ str(soltn[1][x]) for i,x in enumerate (soltn[1],1)]) print('Element values were: ', outstr,'.')LikeLike