Enigmatic Code

Programming Enigma Puzzles

Tantalizer 421: Present time

From New Scientist #971, 16th October 1975 [link]

“I say”, said young Tommy on Christmas morning, when we had each seen our own presents but no one else’s, “here is a poser based on the tea-strainer, bath hat, bath soap and gloves I gave Jane, Kate, Lucy and Maud. I shall now put three questions and each of the girls must give at least two true answers out of the three”.

He first asked, “Did I give you the tea-strainer?” and got the answers: Yes, Yes, No, No. Then he asked: “Did I give you something for the bath?”, getting the answers: Yes, No, Yes, No. The he asked: “Did I give you something to wear?”, getting the answers: No, Yes, Yes, Yes. (Answers are in alphabetical order of girls).

“Now”, he said to the rest of us, “I can tell you that exactly one girl is in a position to deduce what each other girl got. Can you tell me what each girl did get?”

Due to a typo in New Scientist this puzzle was published as Tantalizer No 42.

[tantalizer421]

One response to “Tantalizer 421: Present time

  1. Jim Randell 18 September 2019 at 8:36 am

    This Python program runs in 108ms.

    Run: [ @repl.it ]

    from collections import defaultdict
    from enigma import subsets, multiset, printf
    
    # gifts
    gifts = ('TS', 'BH', 'BS', 'GS')
    
    # questions
    q1 = lambda x: x == 'TS' # "is tea strainer"
    q2 = lambda x: x in ('BH', 'BS') # "for the bath"
    q3 = lambda x: x in ('BH', 'GS') # "something to wear"
    
    # answers for each girl
    (Y, N) = (1, 0)
    ans = [
      (Y, Y, N), # J
      (Y, N, Y), # K
      (N, Y, Y), # L
      (N, N, Y), # M
    ]
    
    # check the girl with gift <g> gives at least 2 correct responses <rs>
    def correct(g, rs):
      return sum(q(g) == x for (q, x) in zip((q1, q2, q3), rs))
    
    # record possible solutions
    ss = list()
    
    # choose an assignment for the gifts
    for gs in subsets(gifts, size=len, select="P"):
    
      # check each girl gives at least two true answers
      if any(correct(g, rs) < 2 for (g, rs) in zip(gs, ans)): continue
    
      ss.append(gs)
      (J, K, L, M) = gs
      printf("[J={J} K={K} L={L} M={M}]")
    
    # for each girl accumulate the number of scenarios for each gift
    r = defaultdict(multiset)
    for s in ss:
      for (i, x) in enumerate(s):
        r[i].add(x)
    
    # look for scenarios where only one girl is has a unique gift
    for gs in ss:
      if sum(r[i][g] == 1 for (i, g) in enumerate(gs)) != 1: continue
      (J, K, L, M) = gs
      printf("J={J} K={K} L={L} M={M}")
    

    Solution: Jane got the bath soap; Kate got the tea-strainer; Lucy got the gloves; Maud got the bath hat.

    There are three assignments of gifts to girls where each of the girls gives at least 2 correct responses.

    Lucy is always able to deduce what the other girls got knowing her own gift. But in one of the scenarios Maud will also be able to tell, and in another scenario both Jane and Kate can also tell. So the scenario where only Lucy can tell is the one we are interested in.

    J=TS; K=GS; L=BS; M=BH
    J=BS; K=TS; L=BH; M=GS
    J=BS; K=TS; L=GS; M=BH [SOLUTION]

Leave a Comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: