Teaser 3208: The scores are all square
From The Sunday Times, 17th March 2024 [link] [link]
For Skaredahora’s quartet four players read the same musical score, but from different compass directions. There are symbols of three types, indicating different whole number beat durations, on a square 17×17 grid. Each player reads the beat position in their left-to-right direction, and pitch in their bottom-to-top.
Each player plays four notes; South reads a plus at (beat,pitch) position (3,12), a circle at (14,1), a cross at (16,3), and a plus at beat 9. For example, if a cross indicates three beats, South plays a note of pitch 3 at beat 16, which is still sounding at beats 17 and 18, while East plays a note of pitch 2 sounding at beats 3, 4 and 5.
No player sounds more than one note at the same time. All possible pitch differences between notes sounding simultaneously from different players occur, except zero and exactly one other value.
Which non-zero pitch difference never occurs? What pitch does South play at beat 9?
[teaser3208]









Jim Randell 6:10 pm on 15 March 2024 Permalink |
This program considers possible positions for the unspecified “+” note, and then constructs the notes heard at each beat for each player and checks the remaining constraints.
It runs in 59ms. (Internal runtime is 1.8ms).
Run: [ @replit ]
from enigma import (irange, inf, tuples, cproduct, subsets, diff, singleton, printf) # fill out beats for notes in <X>, durations <dd> def beats(X, dd): bs = [0] * 22 for (b, p, d) in X: for i in irange(dd[d]): i += b if bs[i] != 0: return bs[i] = p return bs # check a set of beats def check(bs): if None in bs: return # find differences between non-zero pitches ds = set() for ps in zip(*bs): ds.update(abs(x - y) for (x, y) in subsets(filter(None, ps), size=2)) # differences exclude 0 and exactly one other value if 0 in ds: return return singleton(diff(irange(1, 16), ds)) # duration symbols ks = "ox+" # suppose the unspecified '+' is at pitch <x> for S for x in irange(1, 17): # construct the notes (<beat>, <pitch>, <duration>) for each player S = [(3, 12, '+'), (9, x, '+'), (14, 1, 'o'), (16, 3, 'x')] N = list((18 - b, 18 - p, d) for (b, p, d) in S) W = list((18 - p, b, d) for (b, p, d) in S) E = list((p, 18 - b, d) for (b, p, d) in S) # determine maximum possible note duration dm = dict((k, inf) for k in ks) for X in [S, N, W, E]: for ((a, _, k), (b, _, _)) in tuples(sorted(X), 2): dm[k] = min(dm[k], b - a) if 0 in dm.values(): continue # choose durations for ds in cproduct(irange(1, dm[k]) for k in ks): if len(set(ds)) != 3: continue dd = dict(zip(ks, ds)) # record pitches on each beat (bS, bN, bW, bE) = (beats(X, dd) for X in [S, N, W, E]) k = check((bS, bN, bW, bE)) if not k: continue # output solution printf("S={bS}", bS=bS[1:]) printf("N={bN}", bN=bN[1:]) printf("W={bW}", bW=bW[1:]) printf("E={bE}", bE=bE[1:]) printf("x={x} dd={dd} -> k={k} S[9]={S9}", S9=bS[9]) printf()Solution: A pitch difference of 4 does not occur. South plays pitch 17 at beat 9.
The note durations are:
Here is a diagram of the notes played:
LikeLike
Frits 3:08 pm on 22 March 2024 Permalink |
@Jim, only thing to improve for a general solution is getting rid of the hardcoded 22 in line 5.
LikeLike
Jim Randell 3:16 pm on 22 March 2024 Permalink |
Yes. It can be replaced by
(17 + max(dd.values())).LikeLike
Frits 5:23 pm on 16 March 2024 Permalink |
Based on part of Jim’s first published program.
from enigma import SubstitutedExpression, subsets # invalid digit / symbol assignments d2i = dict() for d in range(0, 10): vs = set() if d == 0: vs.update('KLM') if d > 1: vs.update('U') if d > 2: vs.update('KL') # by manual inspection of S resp. N if d > 5: vs.update('M') # by manual inspection of S d2i[d] = vs # check for 15 different pitch differences (without zero) def check(K, L, M, UV): S = sorted([(3, 12, M), (9, UV, M), (14, 1, K), (16, 3, L)]) E = sorted([(UV, 9, M), (1, 4, K), (3, 2, L), (12, 15, M)]) N = sorted([(2, 15, L), (4, 17, K), (9, 18 - UV, M), (15, 6, M)]) W = sorted([(18 - UV, 9, M), (6, 3, M), (15, 16, L), (17, 14, K)]) d = dict() for pl in [S, E, N, W]: done = set() for (b, p, s) in pl: for j in range(s): # no simultaneous notes by the same player if (k := b + j - 1) in done: return False d[k] = d.get(k, []) + [p] done.add(k) # pitch differences diffs = set(abs(p2 - p1) for vs in d.values() for p1, p2 in subsets(vs, 2)) if 0 in diffs or len(diffs) != 15: return False return set(range(1, 17)).difference(diffs).pop() # the alphametic puzzle p = SubstitutedExpression( [ # duration 'o': K, duration 'x': L, duration '+': M # the unspecified pitch "0 < UV < 18", # main checks "(missing := check(K, L, M, UV)) != 0", ], answer="(K, L, M, UV, missing)", d2i=d2i, # different whole number beat durations distinct=("KLM"), env=dict(check=check), verbose=0, # use 256 to see the generated code ) # print answers for ans in p.answers(): print(f"{ans}") print("answer: pitch difference that never occurs:", ans[4]) print(" South plays pitch", ans[3], "at beat 9")LikeLike