Tagged: by: Mary Connor Toggle Comment Threads | Keyboard Shortcuts

  • Unknown's avatar

    Jim Randell 3:34 pm on 14 January 2026 Permalink | Reply
    Tags: by: Mary Connor   

    Brain teaser 983: Superchamp 

    From The Sunday Times, 24th May 1981 [link]

    The five champion athletes competed against one another in their five special events to decide who was the supreme champion (the one with the highest number of points). Three points were awarded for the winner in each event. two points for second place, and one for third.

    The Superchamp won more events than anyone else. All scored a different number of points, and all scored in a different number of events.

    Ben and Colin together scored twice as many points as Fred. Eddie was the only one to win his own special event, and in it the Superchamp came second. In another event Eddie gained one point less than the hurdler. The hurdler only came third in the hurdles, which was won by Denis, who was last in the long jump but scored in the sprint.
    Fred won the long jump and was second in the walk, but came nowhere in the hurdles.

    Ben scored in the long jump and Colin scored in the sprint. The thousand-metre man was third in two events. The long jumper scored more points than the sprinter.

    Who was the [long] jumper, and what was his score?

    This puzzle is included in the book The Sunday Times Book of Brainteasers (1994).

    [teaser983]

     
    • Jim Randell's avatar

      Jim Randell 3:35 pm on 14 January 2026 Permalink | Reply

      There are a lot of conditions to this puzzle, so I used the minizinc.py library to allow me to construct a declarative model for it in MiniZinc, which is then solved, and the Python program used to format the solutions.

      It runs in 545ms.

      from enigma import (require, printf)
      from minizinc import MiniZinc
      
      require("sys.version", "3.6") # needed to support [ use_embed=1 ]
      
      # indices for names and events (1..5)
      (B, C, D, E, F) = (1, 2, 3, 4, 5)
      (hurdles, long_jump, sprint, m1000, walk) = (1, 2, 3, 4, 5)
      
      # construct the MiniZinc model
      m = MiniZinc([
        'include "globals.mzn"',
      
        # scores for the competitors in each event: pts[event, competitor] = score
        "array [1..5, 1..5] of var 0..3: pts",
      
        # scores in each event are: 3, 2, 1, 0, 0
        "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 3) = 1)", # 1st = 3pts
        "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 2) = 1)", # 2nd = 2pts
        "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 1) = 1)", # 3rd = 1pts
        "constraint forall (i in 1..5) (sum (j in 1..5) (pts[i, j] = 0) = 2)", # unplaced = 0pts
      
        # functions:
        "function var int: points(var int: j) = sum (i in 1..5) (pts[i, j])",
        "function var int: wins(var int: j) = sum (i in 1..5) (pts[i, j] = 3)",
        "function var int: scored(var int: j) = sum (i in 1..5) (pts[i, j] > 0)",
      
        # "the superchamp scored more points than anyone else"
        "var 1..5: S",
        "constraint forall (j in 1..5 where j != S) (points(j) < points(S))",
      
        # "the superchamp won more events than anyone else"
        "constraint forall (j in 1..5 where j != S) (wins(j) < wins(S))",
      
        # each competitor scored a different number of points
        "constraint all_different (j in 1..5) (points(j))",
      
        # each competitor scored in a different number of events
        "constraint all_different (j in 1..5) (scored(j))",
      
        # "B and C together scored twice as many points as F"
        "constraint points({B}) + points({C}) = 2 * points({F})",
      
        # "E was the only one to win his own event"
        # "and in that event the superchamp came second"
        "array [1..5] of var 1..5: spe",
        "constraint all_different(spe)",
        "constraint forall (j in 1..5) ((j == {E}) <-> (pts[spe[j], j] = 3))",
        "constraint pts[spe[{E}], S] = 2",
      
        # "in another event E gained 1 point less than the hurdler"
        "var 1..5: hurdler",
        "constraint spe[hurdler] = {hurdles}",
        "constraint exists (i in 1..5) (pts[i, {E}] + 1 = pts[i, hurdler])",
      
        # "the hurdler only came third in hurdles"
        "constraint pts[{hurdles}, hurdler] = 1",
      
        # "hurdles was won by D"
        "constraint pts[{hurdles}, {D}] = 3",
      
        # "D came last in long jump"
        "constraint pts[{long_jump}, {D}] = 0",
      
        # "D scored in the sprint"
        "constraint pts[{sprint}, {D}] > 0",
      
        # "F won the long jump"
        "constraint pts[{long_jump}, {F}] = 3",
      
        # "F was 2nd in the walk"
        "constraint pts[{walk}, {F}] = 2",
      
        # "F did not score in hurdles"
        "constraint pts[{hurdles}, {F}] = 0",
      
        # "B scored in the long jump"
        "constraint pts[{long_jump}, {B}] > 0",
      
        # "C scored in the sprint"
        "constraint pts[{sprint}, {C}] > 0",
      
        # "the 1000m man was 3rd in 2 events"
        "var 1..5: m1000er",
        "constraint spe[m1000er] = {m1000}",
        "constraint sum (i in 1..5) (pts[i, m1000er] = 1) = 2",
      
        # "the long jumper scored more points than the sprinter"
        "var 1..5: long_jumper",
        "constraint spe[long_jumper] = {long_jump}",
        "var 1..5: sprinter",
        "constraint spe[sprinter] = {sprint}",
        "constraint points(long_jumper) > points(sprinter)",
      
      ], use_embed=1)
      
      
      # map indices back to names / events (for output)
      name = {1: "Ben", 2: "Colin", 3: "Denis", 4: "Eddie", 5: "Fred"}
      event = {1: "hurdles", 2: "long jump", 3: "sprint", 4: "1000m", 5: "walk"}
      
      # solve the model and find:
      # pts = results in each event
      # spe = special event for each competitor
      for (pts, spe) in m.solve(solver="minizinc -a", result="pts spe"):
        # collect points
        t = dict((k, 0) for k in name.keys())
      
        # output the results for each event
        for (i, rs) in enumerate(pts, start=1):
          (p1, p2, p3) = (rs.index(p) + 1 for p in (3, 2, 1))
          printf("{e}: 1st = {p1}, 2nd = {p2}, 3rd = {p3}", e=event[i], p1=name[p1], p2=name[p2], p3=name[p3])
          # collect points
          t[p1] += 3
          t[p2] += 2
          t[p3] += 1
        printf()
      
        # determine superchamp
        S = max(t.keys(), key=t.get)
        assert all(k == S or v < t[S] for (k, v) in t.items())
      
        # output the results for each competitor
        for j in sorted(event.keys()):
          printf("{j} [{e}]: {t} points{S}", j=name[j], e=event[spe[j - 1]], t=t[j], S=(' [SUPERCHAMP]' if j == S else ''))
        printf("--")
        printf()
      

      Solution: Denis is the long jumper. He scored 5 points.

      The program finds 2 possible scenarios:

      hurdles: 1st = Denis, 2nd = Eddie, 3rd = Ben
      long jump: 1st = Fred, 2nd = Ben, 3rd = Eddie
      sprint: 1st = Ben, 2nd = Denis, 3rd = Colin
      1000m: 1st = Eddie, 2nd = Ben, 3rd = Fred
      walk: 1st = Ben, 2nd = Fred, 3rd = Eddie

      Ben [hurdles]: 11 points [SUPERCHAMP]
      Colin [sprint]: 1 points
      Denis [long jump]: 5 points
      Eddie [1000m]: 7 points
      Fred [walk]: 6 points

      hurdles: 1st = Denis, 2nd = Eddie, 3rd = Colin
      long jump: 1st = Fred, 2nd = Ben, 3rd = Colin
      sprint: 1st = Colin, 2nd = Denis, 3rd = Eddie
      1000m: 1st = Eddie, 2nd = Colin, 3rd = Fred
      walk: 1st = Colin, 2nd = Fred, 3rd = Eddie

      Ben [sprint]: 2 points
      Colin [hurdles]: 10 points [SUPERCHAMP]
      Denis [long jump]: 5 points
      Eddie [1000m]: 7 points
      Fred [walk]: 6 points

      The solution published in the book (which runs to 3 pages) only gives the first of these solutions.

      I think this is due to the interpretation of “In another event Eddie gained one point less than the hurdler”. The book solution seems to infer (hurdler = 3pts, Eddie = 2pts) or (hurdler = 2pts, Eddie = 1pt), and concludes it is not possible for C to be the champ.

      And in the first scenario, in the long jump, we have: the hurdler (Ben) scores 2pts (2nd place), and Eddie scores 1pt (3rd place).

      However, I think the wording also allows (hurdler = 1pt, Eddie = 0pts), and in the second scenario, in the long jump, we have: the hurdler (Colin) scores 1pt (3rd place), and Eddie scores 0pts (unplaced).

      Like

    • Frits's avatar

      Frits 3:06 pm on 17 January 2026 Permalink | Reply

      from itertools import permutations
      
      '''        3   2   1       
      hurdles    A   F   K        
      long J     B   G   L        
      sprint     C   H   M              super=Superchamp
      1000m      D   I   N        
      Walk       E   J   O        
      '''
      
      sports = [-1, -1, -1, -1, -1]
      (ben, colin, denis, eddie, fred) = range(5)
      
      dgts, sols = set(range(5)), set()
      
      A = denis # Denis won hurdles
      B = fred  # Fred won the long jump
      J = fred  # Fred was 2nd in the walk
      
      # Fred came nowhere in the hurdles
      for F, K in permutations(dgts - {A, fred}, 2):    # hurdles
        # hurdler (K) came 3rd in the hurdles, Eddie is no hurdler
        if eddie == K: continue
        for G, L in permutations(dgts - {B, denis}, 2): # Denis last in long jump
          if 0 not in {G, L} : continue                 # Ben scored in long jump
          for C, H, M in permutations(dgts, 3):         # sprint
            # Colin and Denis scored in the sprint
            if not {C, H, M}.issuperset({colin, denis}): continue 
            for D, I, N in permutations(dgts, 3):       # 1000m
              for E, O in permutations(dgts - {J}, 2):  # walk
                gold   = [A, B, C, D, E]
                silver = [F, G, H, I, J]
                bronze = [K, L, M, N, O]
                # Eddie was the only one to win his own special event
                if eddie not in gold: continue
                scores = [A, F, K, B, G, L, C, H, M, D, I, N, E, J, O]
                scored = [scores.count(i) for i in range(5)]
                # all scored in a different number of events.
                if len(set(scored)) != 5: continue
                
                pts = [sum([3 - (i % 3) for i, s in enumerate(scores) if s == j]) 
                       for j in range(5)]
                # all scored a different number of points
                if len(set(pts)) != 5: continue
                # Ben and Colin together scored twice as many points as Fred
                if pts[ben] + pts[colin] != 2 * pts[fred]: continue
                # the Superchamp won more events than anyone else ( >= 2)
                sups = sorted((f, i) for i in range(5) if (f := gold.count(i)) > 1)
                if not sups or (len(sups) == 2 and len(set(gold)) == 3): continue
                
                super = sups[-1][1]
                # once the Superchamp came 2nd after Eddie
                if super == eddie or super not in silver: continue
                # the Superchamp had the highest number of points
                if pts[super] != max(pts): continue
                
                sports[0] = K  # hurdler only came third in the hurdles
                      
                # check sports where Eddie and Superchamp ended 1 and 2
                for e, (g, s) in enumerate(zip(gold, silver)):
                  if (g, s) != (eddie, super): continue
                  
                  if e == 0: continue # Eddie is not the hurdler
                  # in another event Eddie gained one point less than the hurdler
                  for i, gsb in enumerate(zip(gold, silver, bronze)):
                    if ((K, eddie) in zip(gsb, gsb[1:]) or 
                        (eddie not in gsb and gsb[-1] == K)): break
                  else: # no break
                    break    
                  
                  sports_ = sports.copy()
                  sports_[e] = eddie  # Eddie performs sport <e>
                  # assign people to remaining sports
                  for p in permutations(dgts - {eddie, K}):
                    sports__ = sports_.copy()
                    j = 0
                    for i in range(5):
                      if sports_[i] != -1: continue
                      sports__[i] = p[j]
                      j += 1
                    
                    # Eddie was the only one to win his own special event
                    for i, s in enumerate(sports__):
                      if gold[i] == s and s != eddie: break
                    else: # no break  
                      # the long jumper scored more points than the sprinter
                      if not (pts[sports__[1]] > pts[sports__[2]]): continue
                      # the thousand-metre man was third in two events
                      if bronze.count(sports__[3]) != 2: continue
                      # store solution
                      sols.add((sports__[1], pts[sports__[1]]))
      
      names = "Ben Colin Denis Eddie Fred".split()                
      print("answer:", ' or '.join(names[a] + ' with score ' + str(s) 
                                    for a, s in sols))         
      

      Like

  • Unknown's avatar

    Jim Randell 9:06 am on 23 November 2021 Permalink | Reply
    Tags: by: Mary Connor   

    Brain-Teaser 887: The valetudinarians 

    From The Sunday Times, 6th August 1978 [link]

    “We have just been discussing our health”, said Alf, “and we have discovered that between us we share the same five complaints, and the same prescribed tablets for them. Each of us has two complaints, but no two have both the same, and no more than two of us take each sort of tablets. For instance two take red tablets, two blue, and so on. I do not have green ones. I take one lot the same as Ed, but they are not yellow, and I do not take kidney tablets”.

    Bob said: “I do not have green tablets. One heart patient also has tablets for sleeplessness”.

    Cyril said: “I do not have kidney tablets. I take one lot the same as Ed which are not for the heart. I do not take blue ones”.

    Don said: “I do not have heart trouble. My tablets are not yellow. Those who take green tablets do not also take blue ones”.

    Ed said: “I take white tablets which are not for the heart. The ones with nerves do not have indigestion, and nerve tablets are not yellow”.

    What colour were the heart tablets? Who took those for nerves?

    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.

    [teaser887]

     
    • Jim Randell's avatar

      Jim Randell 9:08 am on 23 November 2021 Permalink | Reply

      I assumed each colour tablet is prescribed for the same condition in each patient.

      This Python program uses the [[ choose() ]] function from enigma.py, which I thought I would use more when I implemented it. It runs in 65ms.

      Run: [ @replit ]

      from enigma import (subsets, ordered, choose, intersect, singleton, multiset, join, printf)
      
      # tablet colours
      tablets = "BGRWY"
      
      # map complaints to tablets
      for (K, H, N, I, S) in subsets(tablets, size=len, select="P"):
      
        # "white tablets are not for the heart"
        if H == 'W': continue
      
        # "nerve tablets are not yellow"
        if N == 'Y': continue
      
        # there are 2 invalid combinations: nerves + indigestion, green + blue
        invalid = { ordered(N, I), ('B', 'G') }
        values = set(s for s in subsets(tablets, size=2)).difference(invalid)
      
        # choose tablets for each person:
        def fE(Es):
          # E has white
          if 'W' not in Es: return False
          return True
      
        def fA(Es, As):
          # A does not have green or kidney
          if 'G' in As or K in As: return False
          # A has one tablet the same as E, and it isn't yellow
          AE = singleton(intersect([As, Es]))
          if AE is None or AE == 'Y': return False
          return True
      
        def fC(Es, As, Cs):
          # C does not have kidney or blue
          if K in Cs or 'B' in Cs: return False
          # C has one tablet the same as E, and it isn't heart
          CE = singleton(intersect([Cs, Es]))
          if CE is None or CE == H: return False
          return True
      
        def fD(Es, As, Cs, Ds):
          # D does not have heart or yellow
          if H in Ds or 'Y' in Ds: return False
          return True
      
        def fB(Es, As, Cs, Ds, Bs):
          # B does not have green
          if 'G' in Bs: return False
          return True
      
        # make the choices
        for vs in choose(values, [fE, fA, fC, fD, fB], distinct=1):
          # one of them has heart + sleeplessness
          if not (ordered(H, S) in vs): continue
          # each tablet is used by two people
          if not multiset.from_seq(*vs).all_same(2): continue
      
          # output solution
          (Es, As, Cs, Ds, Bs) = (join(v, sep="+") for v in vs)
          printf("A={As} B={Bs} C={Cs} D={Ds} E={Es} [K={K} H={H} N={N} I={I} S={S}]")
      

      Solution: Heart tablets are blue. Cyril and Don took tablets for nerves.

      The complete situation is:

      Alf: blue (heart); yellow (indigestion)
      Bob: red (kidney); yellow (indigestion)
      Cyril: green (nerves); white (sleeplessness)
      Don: green (nerves); red (kidney)
      Ed: blue (heart); white (sleeplessness)

      Like

    • Frits's avatar

      Frits 1:32 pm on 30 November 2021 Permalink | Reply

        
      from itertools import combinations as comb, permutations as perm
      
      # filter on tablet, complaint and shared tablets (with, type, exclusion) 
      def filter(lst, exc_tabl, exc_cmpl=99, shr_with=[], shr_t=0, shr_e={}):
        if shr_with:
          shr_set = {shr_with[0][shr_t], shr_with[1][shr_t]}
          frz_set = {frozenset(), frozenset(shr_e)}
          
        return [(x, y) for x, y in lst if all(e not in {x[i], y[i]} 
               for i, e in enumerate([exc_tabl, exc_cmpl])) and (not shr_with or 
               shr_set.intersection({x[shr_t], y[shr_t]}) not in frz_set)]
      
      guys = ["Alf", "Bob", "Cyril", "Don", "Ed"]
      tablets = ["red", "blue", "green", "white", "yellow"]
      # [0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
      sorted_tablets = [i for i in range(5) for _ in range(2)]
      
      # red    0       indigestion   0
      # blue   1       heart         1
      # green  2       kidney        2
      # white  3       sleeplessness 3 
      # yellow 4       nerves        4
      
      # loop over complaints per tablet
      for p in perm(range(5)):
        # "white tablets are not for the heart"
        # "nerve tablets are not yellow"
        if p[3] == 1 or p[4] == 4: continue
        
        # combine two out of (tablets, complaints) list
        # there are 2 invalid combinations: nerves + indigestion, green + blue
        cmbs = [(x, y) for x, y in comb([(i, z) for i, z in enumerate(p)], 2) 
               if sorted((x[1], y[1])) != [0, 4] and
                  sorted((x[0], y[0])) != [1, 2]]
        
        # one of them has heart + sleeplessness          
        if all(sorted([x[1], y[1]]) != [1, 3] for x, y in cmbs): continue
        
        # E has white
        for E in [(x, y) for x, y in cmbs if 3 in {x[0], y[0]}]:
          notE = set(cmbs).difference({E})
          # A does not have green or kidney
          # A has one tablet the same as E, and it isn't yellow
          for A in filter(notE, 2, 2, E, 0, [4]):
            notAE = set(notE).difference({A})
            # C does not have kidney or blue
            # C has one tablet the same as E, and it isn't heart
            for C in filter(notAE, 1, 2, E, 1, [1]):
              notAEC = set(notAE).difference({C})
              # D does not have heart or yellow
              for D in filter(notAEC, 4, 1):
                notAECD = set(notAEC).difference({D})
                # B does not have green
                for B in filter(notAECD, 2):
                  ABCDE = [A, B, C, D, E]
                  
                  # each tablet is sorted by two people
                  if sorted(z for x, y in ABCDE for z in (x[0], y[0])) != \
                     sorted_tablets: continue
                  
                  # one of them has heart + sleeplessness     
                  if all(sorted([x[1], y[1]]) != [1, 3] for x, y in ABCDE): 
                    continue
                  
                  heart = set(x[0] if x[1] == 1 else y[0] 
                              for x, y in ABCDE if 1 in {x[1], y[1]})
                  if len(heart) != 1: continue 
                  print(f"Heart tablets are {tablets[heart.pop()]}.")
                  
                  nerves = [i for i, (x, y) in enumerate(ABCDE) 
                            if 4 in {x[1], y[1]}]
                  print(f"{guys[nerves[0]]} and {guys[nerves[1]]} "
                        f"took tablets for nerves")
      

      Like

  • Unknown's avatar

    Jim Randell 9:54 am on 26 August 2021 Permalink | Reply
    Tags: by: Mary Connor   

    Brain-Teaser 840: Cake mix variations 

    From The Sunday Times, 21st August 1977 [link]

    A small party was held to promote a brand of Cake Mix. There were five varieties of cake, five beverages, and five sorts of savouries offered.

    I asked a sample group of five what they had chosen, and learned that each had had a different drink, a different slice of cake and two savouries.

    No one had picked the same two savouries as any other, and no more than two people had the same savoury.

    No one had cake of the same flavour as her beverage (tea being paired with plain sponge in this case).

    Dot told me that she had no coffee in any form, no cheese and no egg, but she did have a sausage roll and one thing with orange flavour.

    Eve had lemon drink, but no egg, and said that the one who had both egg and cheese did not drink coffee, but the tea drinker had cheese nibbles.

    Fran said the one who drank chocolate had lemon cake. Fran had shrimp vol-au-vent, and only one of the shrimp eaters had lemon in either form.

    Gill had a sausage roll and one orange item, and said that the one who had cheese had chocolate cake.

    Helen told me that the one who had coffee cake had a ham sandwich, but no cheese, and no one had stuffed egg as well as shrimp.

    Who had the ham sandwiches ?

    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.

    [teaser840]

     
    • Jim Randell's avatar

      Jim Randell 9:55 am on 26 August 2021 Permalink | Reply

      Here is a solution using the [[ SubstitutedExpression ]] solver from the enigma.py library.

      It runs in 81ms.

      #! python3 -m enigma -rr
      
      # assign values to the names:
      #   Dot = 1; Eve = 2; Fran = 3; Gill = 4; Helen = 5
      #
      # and then assign these values to the comestibles:
      #   cakes: sponge = A; coffee = B; orange = C; lemon = D; chocolate = E
      #   drinks: tea = F; coffee = G; orange = H; lemon = I; chocolate = J
      #   savouries: cheese = K & L; egg = M & N; s roll = P & Q; shrimp = R & S; ham s = T & U
      
      SubstitutedExpression
      
      --digits="1-5"
      --distinct="ABCDE,FGHIJ,KMPRT,LNQSU,AF,BG,CH,DI,EJ,KL,MN,PQ,RS,TU"
      
      # remove duplicate solutions
      "T < U"
      
      # "Dot has no coffee, no cheese, no egg"
      "B != 1"
      "G != 1"
      "K != 1"
      "L != 1"
      "M != 1"
      "N != 1"
      
      # "Dot has a sausage roll, and something orange"
      "P == 1 or Q == 1"
      "C == 1 or H == 1"
      
      # "Eve had lemon drink"
      "I == 2"
      
      # "Eve had no egg"
      "M != 2"
      "N != 2"
      
      # "someone had egg, cheese and not coffee"
      "((M == K or M == L) and G != M) or ((N == K or N == L) and G != N)"
      
      # "tea drinker had cheese"
      "F == K or F == L"
      
      # "hot chocolate had lemon cake"
      "J == D"
      
      # "Fran had shrimp"
      "R == 3 or S == 3"
      
      # "only one shrimp eater also had lemon"
      "(R == D or R == I) + (S == D or S == I) = 1"
      
      # "Gill had sausage roll and something orange"
      "P == 4 or Q == 4"
      "C == 4 or H == 4"
      
      # "someone had cheese and chocolate cake"
      "(K == E) or (L == E)"
      
      # "coffee cake had a ham sandwich, but no cheese"
      "B == T or B == U"
      "B != K and B != L"
      
      # "no-one had egg and shrimp"
      "is_disjoint(([M, N], [R, S]))"
      
      # mention A
      "A > 0"
      
      # [optional]
      --template="(A B C D E) (F G H I J) (K L) (M N) (P Q) (R S) (T U)"
      --solution=""
      --denest=-1  # apply fix for CPython
      

      Solution: Dot and Eve had the ham sandwiches.

      The full solution is:

      D: Sponge cake; orange juice; sausage roll + ham sandwich
      E: Coffee cake; lemon squash; shrimp + ham sandwich
      F: Chocolate cake; tea; cheese + shrimp
      G: Orange cake; coffee; egg + sausage roll
      H: Lemon cake; hot chocolate; cheese + egg

      Like

  • Unknown's avatar

    Jim Randell 9:17 am on 12 March 2020 Permalink | Reply
    Tags: by: Mary Connor   

    Brain-Teaser 515: [Herb gardens] 

    From The Sunday Times, 25th April 1971 [link]

    Five little girls wanted herb gardens. Mother gave them five kinds and said:

    “There are three clumps of each sort. Now each take three clumps, but so that you have three different kinds in your garden, and so that not one of you has the same three as anyone else.”

    Anne now has two the same as Eve, whose third is common to Beth and Carol. Carol has two the same as Beth, but not the parsley, which Beth has. Dot has mint, and shares two others with Anne. Eve didn’t really like any of Dot’s choice, but they have to share the one Beth and Carol don’t have. Dot doesn’t have rue, and only one person has rue with mint, and one with parsley and thyme.

    Who had sage and who had thyme?

    This puzzle was originally published with no title.

    [teaser515]

     
    • Jim Randell's avatar

      Jim Randell 9:18 am on 12 March 2020 Permalink | Reply

      Programatically, we can try all possible assignments of selections of herbs to the girls.

      This Python program runs in 94ms.

      Run: [ @repl.it ]

      from enigma import subsets, join, printf
      
      # possible choices
      ss = list(map(set, subsets("MPRST", size=3, select="C")))
      
      # choose different sets for each of the girls
      for (A, B, C, D, E) in subsets(ss, size=5, select="P"):
      
        # A does not have M
        # B has P
        # C does not have P
        # D has M, does not have R
        if 'M' in A or 'P' not in B or 'P' in C or 'M' not in D or 'R' in D: continue
      
        # A has 2 the same as E
        AnE = A.intersection(E)
        if len(AnE) != 2: continue
      
        # and E's other one is common to B and C
        # B and C share 2
        BnC = B.intersection(C)
        if len(BnC) != 2: continue
        EdA = E.difference(A)
        if not EdA.issubset(BnC): continue
      
        # A and D share 2
        AnD = A.intersection(D)
        if len(AnD) != 2: continue
      
        # D and E share 1, and neither B nor C have it
        DnE = D.intersection(E)
        if len(DnE) != 1 or DnE.issubset(B.union(C)): continue
        
        # only one has M+R, only one has P+T
        count = lambda s: sum(x.issuperset(s) for x in (A, B, C, D, E))
        if not(count('MR') == 1 and count('PT') == 1): continue
      
        # output solutions
        collect = lambda k: join(x for (x, s) in zip("ABCDE", (A, B, C, D, E)) if k in s)
        (A, B, C, D, E) = (join(sorted(x)) for x in (A, B, C, D, E))
        printf("A={A} B={B} C={C} D={D} E={E} -> S={S} T={T}", S=collect('S'), T=collect('T'))
      

      Solution: Anne, Dot, Eve have sage. Beth, Carol, Eve have thyme.

      There are two possible sets of herbs (B has a choice of two different selections):

      A: PRS
      B: MPT / PRT
      C: MRT
      D: MPS
      E: RST

      Like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Design a site like this with WordPress.com
Get started