From The Sunday Times, 21st January 1962 [link]
This unusual instrument is operated by selecting one of the four switch positions: A, B, C, D, and turning the power on. The effects are:
A: The pratching valve glows and the queech obulates;
B: The queech obulates and the urfer curls up, but the rumption does not get hot;
C: The sneeveling rod turns clockwise, the pratching valve glows and the queech fails to obulate;
D: The troglodyser gives off hydrogen but the urfer does not curl up.
Whenever the pratching valve glows, the rumption gets hot. Unless the sneeveling rod turns clockwise, the queech cannot obulate, but if the sneeveling rod is turning clockwise the troglodyser will not emit hydrogen. If the urfer does not curl up, you may be sure that the rumption is not getting hot.
In order to get milk chocolate from the machine, you must ensure:
(a) that the sneeveling rod is turning clockwise AND;
(b) that if the troglodyser is not emitting hydrogen, the queech is not obulating.
1. Which switch position would you select to get milk chocolate?
If, tiring of chocolate, you wish to receive the Third Programme, you must take care:
(a) that the rumption does not get hot AND;
(b) either that the urfer doesn’t curl and the queech doesn’t obulate or that the pratching valve glows and the troglodyser fails to emit hydrogen.
2. Which switch position gives you the Third Programme?
No setter was given for this puzzle.
This puzzle crops up in several places on the web. (Although maybe it’s just because it’s easy to search for: “the queech obulates” doesn’t show up in many unrelated pages).
And it is sometimes claimed it “appeared in a national newspaper in the 1930s” (although the BBC Third Programme was only broadcast from 1946 to 1967 (after which it became BBC Radio 3)), but the wording always seems to be the same as the wording in this puzzle, so it seems likely this is the original source (at least in this format).
“Omnibombulator” is also the title of a 1995 book by Dick King-Smith.
[teaser44]
Jim Randell 9:20 am on 15 December 2020 Permalink |
We can use the [[
DominoGrid()]] solver from the enigma.py library to solve this puzzle.Run: [ @repl.it ]
Solution: The completed grid is shown below:
LikeLike
Frits 2:00 pm on 19 December 2020 Permalink |
You have to press a key each time for finding new dominoes/stones.
import os from collections import defaultdict # grid dimensions (rows, columns) (R, C) = (7 ,8) g = [ 1, 6, 3, 3, 5, 6, 6, 0, 2, 6, 2, 5, 4, 4, 3, 3, 3, 6, 6, 5, 0, 4, 1, 3, 2, 4, 5, 0, 0, 1, 1, 4, 4, 4, 1, 1, 0, 2, 0, 6, 0, 4, 3, 2, 0, 2, 2, 6, 2, 1, 5, 5, 5, 5, 1, 3, ] # return coordinates of index number <n> in list <g> coord = lambda n: (n // C, n % C) # return index number in list <g> gnum = lambda x, y: x * C + y # return set of stone numbers in list <li>, like {'13', '15', '12'} domnums = lambda li: set("".join(sorted(str(li[i][1]) + str(li[i+1][1]))) for i in range(0, len(li), 2)) # build dictionary of coordinates per stone def collect_coords_per_stone() : # empty the dictionary for k in coords_per_stone: coords_per_stone[k] = [] for (i, d) in enumerate(g): if d < 0: continue # already placed? # (x, y) are the coordinates in the 2 dimensional matrix (x, y) = divmod(i, C) js = list() # horizontally if y < C - 1 and not(g[i + 1] < 0): js.append(i + 1) # vertically if x < R - 1 and not(g[i + C] < 0): js.append(i + C) # try possible placements for j in js: stone = tuple(sorted((g[i], g[j]))) if ((coord(i), coord(j))) in ex: continue if not stone in done: coords_per_stone[stone] += [[coord(i), coord(j)]] # coordinate <mand> has to use stone {mandstone> so remove other possibilities def remove_others(mand, mandstone, reason): global stop mandval = g[gnum(mand[0], mand[1])] stones = stones_per_coord[mand] for i in range(0, len(stones), 2): otherval = stones[i+1][1] if stones[i][0] == mand else stones[i][1] stone = sorted([mandval, otherval]) # stone at pos <mand> unequal to <mandstone> ? if stone != mandstone: otherco = stones[i+1][0] if stones[i][0] == mand else stones[i][0] tup = tuple(sorted([mand, otherco])) if tup in ex: continue print(f"stone at {yellow}{str(tup)[1:-1]}{endc} " f"cannot be {stone} {reason}") ex[tup] = stone stop = 0 # check for unique stones and for a coordinate occurring in all entries def analyze_coords_per_stone(): global step, stop for k, vs in sorted(coords_per_stone.items()): k_stone = tuple(sorted(k)) if len(vs) == 1: pair = vs[0] x = gnum(pair[0][0], pair[0][1]) y = gnum(pair[1][0], pair[1][1]) if list(k_stone) in done: continue print(f"---- place stone {green}{k_stone}{endc} at coordinates " f"{yellow}{pair[0]}, {pair[1]}{endc} (stone occurs only once)") done.append(k_stone) g[x] = g[y] = step step -= 1 stop = 0 elif len(vs) != 0: # look for a coordinate occurring in all entries common = [x for x in vs[0] if all(x in y for y in vs[1:])] if len(common) != 1: continue reason = " (coordinate " + yellow + str(common)[1:-1] + \ endc + " has to use stone " + str(k) + ")" # so remove <common> from other combinations remove_others(common[0], sorted(k), reason) # build dictionary of stones per coordinate def collect_stones_per_coord(): stones = defaultdict(list) # collect stones_per_coord per cell for (i, d) in enumerate(g): if d < 0: continue # already placed? # (x, y) are the coordinates in the 2 dimensional matrix (x, y) = divmod(i, C) js = list() # horizontally if y < C - 1 and not(g[i + 1] < 0): js.append(i + 1) if y > 0 and not(g[i - 1] < 0): js.append(i - 1) # vertically if x < R - 1 and not(g[i + C] < 0): js.append(i + C) if x > 0 and not(g[i - C] < 0): js.append(i - C) # try possible placements for j in js: t = [[coord(i), g[i]], [coord(j), g[j]]] t2 = tuple(sorted((coord(i), coord(j)))) if t2 not in ex: stones[(x, y)] += t return stones # check if only one stone is possible for a coordinate def one_stone_left(): global step, stop for k, vs in sorted(stones_per_coord.items()): if len(vs) != 2: continue pair = vs x = gnum(pair[0][0][0], pair[0][0][1]) y = gnum(pair[1][0][0], pair[1][0][1]) if g[x] < 0 or g[y] < 0: return stone = sorted([g[x], g[y]]) if stone in done: continue print(f"---- place stone {green}{tuple(stone)}{endc} at coordinates " f"{yellow}{str(sorted((pair[0][0], pair[1][0])))[1:-1]}{endc}, " f"(only one possible stone left)") done.append(stone) g[x] = g[y] = step step -= 1 stop = 0 # if n fields only allow for n stones we have a group def look_for_groups(): global stop for n in range(2, 5): for group in findGroups(n, n, list(stones_per_coord.items())): # skip for adjacent fields a1 = any(x[0] == y[0] and abs(x[1] - y[1]) == 1 for x in group[1] for y in group[1]) if a1: continue a2 = any(x[1] == y[1] and abs(x[0] - y[0]) == 1 for x in group[1] for y in group[1]) if a2: continue for d in group[0]: # get stone number tup = tuple(int(x) for x in d) for c in coords_per_stone[tup]: # skip coordinates in our group if len(set(c) & set(group[1])) > 0: continue tup2 = tuple(c) if g[gnum(tup2[0][0], tup2[0][1])] < 0: continue if g[gnum(tup2[1][0], tup2[1][1])] < 0: continue if tup2 in ex: continue print(f"stone at {yellow}{str(tup2)[1:-1]}{endc} cannot be " f"{list(tup)}, group ({', '.join(group[0])}) " f"exists at coordinates {yellow}{str(group[1])[1:-1]}{endc}") ex[tup2] = list(tup) stop = 0 if stop == 0: return # skip the bigger groups # pick <k> elements from list <li> so that all picked elements use <n> values def findGroups(n, k, li, s=set(), f=[]): if k == 0: yield (list(s), f) else: for i in range(len(li)): # get set of stone numbers vals = domnums(li[i][1]) if len(s | vals) <= n: yield from findGroups(n, k - 1, li[i+1:], s | vals, f + [li[i][0]]) def print_matrix(mat, orig): # https://en.wikipedia.org/wiki/Box-drawing_character global g_save nw = '\u250c' # N ne = '\u2510' # W E ho = '\u2500' # S ve = '\u2502' sw = '\u2514' se = '\u2518' numlist = "".join([" " + str(i) for i in range(C)]) + " " print("\n\x1b[6;30;42m" + numlist + "\x1b[0m") for i in range(R): top = "" txt = "" bot = "" prt = 0 for j in range(C): v = mat[i*C + j] # original value ov = orig[i*C + j] if orig[i*C + j] > -1 else " " cb = green if v != g_save[i*C + j] else "" ce = endc if v != g_save[i*C + j] else "" o = orientation(mat, i*C + j, v) if o == 'N': top += nw+ho+ho+ho+ne txt += ve+cb+ " " + str(ov) + " " + ce+ve bot += ve+ " " + ve if o == 'S': top += ve+ " " + ve txt += ve+cb+ " " + str(ov) + " " + ce+ve bot += sw+ho+ho+ho+se if o == 'W': # already handle East as well top += nw+ho+ho+ho+ho+ho+ho+ho+ho+ne txt += ve+cb+ " " + str(ov) + " " + str(orig[i*C + j + 1]) + " " + ce+ve bot += sw+ho+ho+ho+ho+ho+ho+ho+ho+se if o == '': top += " " txt += " " + str(ov) + " " bot += " " print("\x1b[6;30;42m \x1b[0m " + top + "\x1b[6;30;42m \x1b[0m") print("\x1b[6;30;42m" + str(i) + "\x1b[0m " + txt + "\x1b[6;30;42m" + str(i) + "\x1b[0m") print("\x1b[6;30;42m \x1b[0m " + bot + "\x1b[6;30;42m \x1b[0m") print("\x1b[6;30;42m" + numlist + "\x1b[0m") g_save = list(g) def orientation(mat, n, v): if v > -1: return "" # (x, y) are the coordinates in the 2 dimensional matrix (x, y) = divmod(n, C) # horizontally if y < C - 1 and mat[n + 1] == v: return "W" if y > 0 and mat[n - 1] == v: return "E" # vertically if x < R - 1 and mat[n + C] == v: return "N" if x > 0 and mat[n - C] == v: return "S" return "" coords_per_stone = defaultdict(list) stop = 0 step = -1 green = "\033[92m" yellow = "\033[93m" endc = "\033[0m" # end color done = [] ex = defaultdict(list) os.system('cls||clear') g_orig = list(g) g_save = list(g) for loop in range(222): stop = 1 prevstep = step stones_per_coord = collect_stones_per_coord() one_stone_left() if step == prevstep: collect_coords_per_stone() analyze_coords_per_stone() if step < prevstep: print_matrix(g, g_orig) if all(y < 0 for y in g): exit(0) letter = input('Press any key: ') os.system('cls||clear') print() continue # collect again as some possible placements may have been ruled out stones_per_coord = collect_stones_per_coord() look_for_groups() if stop: break print("----------------------- NOT SOLVED -----------------------------") print_matrix(g, g_orig)LikeLike