Brain-Teaser 787: Puzzlers’ office party
From The Sunday Times, 15th August 1976 [link]
Brainbenders and Co., the noted games and puzzles manufacturers, held their office party recently.
The eight from the planning department shared one round table. Pat Robinson and Ann arrived together. Miss Davis looked sensational in her new dress and Mr Armstrong’s suit was fresh from the cleaners.
Red-haired John sat on Miss Jones’s right while Mary sat next-but-one to both Miss Brown and Miss Stevens. Joan only had eyes for Mr Evans, opposite her, while her neighbour, Edna, was interested in Fred, who was sitting beside Bill and next-but-one to Miss Stevens.
Mr Smith was the only man between two girls and Miss Brown the only girl between two fellows. However, only two people sat opposite a person of their own sex.
What was the seating plan?
This puzzle is included in the book The Sunday Times Book of Brain-Teasers: Book 1 (1980). The puzzle text above is taken from the book.
[teaser787]
Jim Randell 12:27 pm on 24 June 2021 Permalink |
I used the [[
SubstitutedExpression]] solver from the enigma.py library to find viable assignments of first/last names to positions 0 to 7 around the table.The following run file finds the assignments of names to positions:
#! python3 -m enigma -rr SubstitutedExpression # we have 8 first names: # Pat, Ann, John, Mary, Joan, Edna, Fred, Bill # A B C D E F G H # # and 8 last names: # Robinson, Jones, Davis, Armstrong, Brown, Stevens, Evans, Smith # S T U V W X Y Z --distinct="ABCDEFGH,STUVWXYZ" # and we need to assign each to a position 0-7 --base=8 # start with Pat Robinson in position 0 --assign="A,0" --assign="S,0" # John sat on Jones' right "(C + 1) % 8 = T" # Mary sat next but 1 to Brown and Stevens "abs(D - W) in {2, 6}" "abs(D - X) in {2, 6}" # Joan was opposite Evans "(E + 4) % 8 = Y" # Joan was next to Edna "abs(E - F) in {1, 7}" # Fred was next to Bill, and next but 1 to Stevens "abs(G - H) in {1, 7}" "abs(G - X) in {2, 6}" # return the positions for each first name and last name --answer="((A, B, C, D, E, F, G, H), (S, T, U, V, W, X, Y, Z))"We are given the genders associated with 7 of the 8 surnames, so only Robinson remains undecided.
The following Python program takes the output of the above run file, and performs the gender checks. It runs in 59ms.
Run: [ @replit ]
from enigma import (SubstitutedExpression, irange, tuples, printf) # load the solver for the names p = SubstitutedExpression.from_file("teaser787.run") # perform the gender checks def check(gs, Smith, Brown): # only 2 people sat opposite a person of the same gender # (i.e. there is exactly 1 pair) if not(sum(gs[i] == gs[i + 4] for i in irange(0, 3)) == 1): return False # find positions of gender X between gender Y def between(X, Y): for (j, i, k) in tuples(irange(0, 7), 3, circular=1): if gs[i] == X and gs[j] == gs[k] == Y: yield i # Smith is the only male between 2 females if not(set(between(0, 1)) == {Smith}): return False # Brown is the only female between 2 males if not(set(between(1, 0)) == {Brown}): return False # looks OK return True # find solutions for first/last names for (s, (fps, lps)) in p.solve(verbose=0): # assign the genders we know: # m = Mr Armstrong, Mr Evans, Mr Smith # f = Miss Davis, Miss Jones, Miss Brown, Miss Stevens # and choose the remaining value (Robinson) for g in (0, 1): # map gs: pos -> gender (0=male, 1=female) gs = dict(zip(lps, [g, 1, 1, 0, 1, 1, 0, 0])) if not check(gs, s['Z'], s['W']): continue # output solution last = dict(zip(lps, ["Robinson", "Jones", "Davis", "Armstrong", "Brown", "Stevens", "Evans", "Smith"])) first = dict(zip(fps, ["Pat", "Ann", "John", "Mary", "Joan", "Edna", "Fred", "Bill"])) for i in irange(0, 7): printf("{i}: ({x}) {first} {last}", i=i + 1, x="mf"[gs[i]], first=first[i], last=last[i]) printf()Solution: The seating plan is (clockwise from Pat Robinson):
LikeLike
Jim Randell 4:03 pm on 24 June 2021 Permalink |
Or with all the code in a single file:
from enigma import SubstitutedExpression, irange, tuples, printf # perform the gender checks def check(ns, gs, Smith, Brown): # map d: pos -> gender (0=male, 1=female) d = dict(zip(ns, gs)) # only 2 people sat opposite a person of the same gender # (i.e. there is exactly 1 pair) if not(sum(d[i] == d[i + 4] for i in irange(0, 3)) == 1): return False # find positions of gender X between gender Y def between(X, Y): for (j, i, k) in tuples(irange(0, 7), 3, circular=1): if d[i] == X and d[j] == d[k] == Y: yield i # Smith is the only male between 2 females if not(set(between(0, 1)) == {Smith}): return False # Brown is the only female between 2 males if not(set(between(1, 0)) == {Brown}): return False # looks OK return True # we have 8 first names: # Pat, Anne, John, Mary, Joan, Edna, Fred, Bill # A B C D E F G H # # and 8 last names: # Robinson, Jones, Davis, Armstrong, Brown, Stevens, Evans, Smith # S T U V W X Y Z p = SubstitutedExpression([ "(C + 1) % 8 = T", # John sat on Jones' right "abs(D - W) in {2, 6}", # Mary sat next but 1 to Brown ... "abs(D - X) in {2, 6}", # ... and Stevens "(E + 4) % 8 = Y", # Joan was opposite Evans ... "abs(E - F) in {1, 7}", # ... and next to Edna "abs(G - H) in {1, 7}", # Fred was next to Bill ... "abs(G - X) in {2, 6}", # ... and next but 1 to Stevens "check([S, T, U, V, W, X, Y, Z], [N, 1, 1, 0, 1, 1, 0, 0], Z, W)", # gender checks ], distinct=("ABCDEFGH", "STUVWXYZ"), base=8, # assign each name a position 0-7 s2d=dict(A=0, S=0), # start with Pat Robinson in position 0 d2i=dict((d, 'N') for d in irange(2, 7)), env=dict(check=check), answer="((A, B, C, D, E, F, G, H), (S, T, U, V, W, X, Y, Z), N)", verbose=0 ) # find solutions for first/last names, and Robinson's gender for (s, (fps, lps, g)) in p.solve(): # output solution gs = dict(zip(lps, [g, 1, 1, 0, 1, 1, 0, 0])) last = dict(zip(lps, ["Robinson", "Jones", "Davis", "Armstrong", "Brown", "Stevens", "Evans", "Smith"])) first = dict(zip(fps, ["Pat", "Anne", "John", "Mary", "Joan", "Edna", "Fred", "Bill"])) for i in irange(0, 7): printf("{i}: ({x}) {first} {last}", i=i + 1, x="mf"[gs[i]], first=first[i], last=last[i]) printf()LikeLike
Frits 11:30 am on 1 July 2021 Permalink |
Adding the following to the run member limits the possibilities to one.
# Smith is the only male between 2 females # this must be John as Fred was next to Bill "C == Z", # Brown is the only female between 2 males # so Brown must be next to John "abs(C - W) in {1, 7} and (abs(G - W) in {1, 7} or abs(H - W) in {1, 7})" # only 2 people sat opposite a person of the same gender # so all males didn't sit opposite each other "4 not in [abs(C - G), abs(C - H)]" # male surnames are Armstrong, Evans and Smith "sorted([C, G, H]) == sorted([V, Y, Z])"LikeLike
Jim Randell 2:36 pm on 1 July 2021 Permalink |
I wasn’t sure if the setter intended us to infer gender from first names (although clearly “Pat” is deliberately ambiguous).
But it turns out that it is not necessary to do so to solve the puzzle, so I didn’t.
LikeLike