Enigmatic Code

Programming Enigma Puzzles

Tantalizer 422: Holy matrimony

From New Scientist #972, 23rd October 1975 [link]

When the five ministers at St. Saviour’s all got divorced, it was a relief. When all announced a remarriage, it was a surprise. When the brides were revealed to be the five ex-wives, it was a sensation. Still, the priggish Dinah was not the first to remarry and there were no direct swaps, so I daresay the decencies were preserved.

The weddings were held on successive Saturdays. Peter’s took place earlier than Anne’s and later than Quentin’s. Barbara’s was later than Tristram’s and earlier than Celia’s.

Peter married Simon’s ex-wife. Barbara got hitched to the man whose former wife married Emily’s ex-husband. Quentin paired up with the lady whose former husband married Dinah. Ronald was spliced with the lady whose ex-husband married Celia.

Who, pray, is now married to whom?

[tantalizer422]

One response to “Tantalizer 422: Holy matrimony

  1. Jim Randell 4 September 2019 at 8:30 am

    This Python program runs in 171ms.

    Run: [ @repl.it ]

    from enigma import subsets, join, printf
    
    # wives and husbands
    wives = list("ABCDE")
    husbands = list("PQRST")
    
    # make a pairing map (x -> y, y -> x)
    def pairs(xs, ys):
      d = dict(zip(xs, ys))
      d.update(zip(ys, xs))
      return d
    
    # make the second marriage pairing
    for s1 in subsets(husbands, size=len, select="P"):
      m2 = pairs(s1, wives)
    
      # collect possible orderings for the weddings
      ws = list()
      for s3 in subsets(wives, size=len, select="P"):
        w = dict((x, i) for (i, x) in enumerate(s3, start=1))
    
        # ordering constraints
        # "D was not the first to remarry"
        if w['D'] == 1: continue
        # "P's wedding was earlier than A's and later than Q's
        if not(w[m2['Q']] < w[m2['P']] < w['A']): continue
        # "B's wedding was later than T's and earlier than C's
        if not(w[m2['T']] < w['B'] < w['C']): continue
    
        ws.append(w)
    
      if not(ws): continue
    
      # make the first marriage pairing
      for s2 in subsets(husbands, size=len, select="P"):
        m1 = pairs(s2, wives)
    
        # no-one keeps their partner
        if any(m1[x] == m2[x] for x in wives): continue
    
        # no-one makes a direct swap
        if any(m2[m1[m2[m1[x]]]] == x for x in wives): continue
    
        # we know some constraints between first and second marriages
        # "P married S's ex-wife"
        if not(m2[m1['S']] == 'P'): continue
        # "B married the man whose former wife married E's ex-husband"
        if not(m1[m2['B']] == m2[m1['E']]): continue
        # "Q married the lady whose former husband married D"
        if not(m1[m2['Q']] == m2['D']): continue
        # "R married the lady whose ex-husband married C"
        if not(m2[m1[m2['R']]] == 'C'): continue
    
        # output solution
        for x in wives:
          printf("{x}: divorced {d}, married {m}", d=m1[x], m=m2[x])
        printf("[order = {ws}]", ws=join((join(sorted(w.keys(), key=(lambda k: w[k]))) for w in ws), sep=", "))
        printf()
    

    Solution: The pairings are: Emily and Quentin, Dinah and Tristram, Barbara and Ronald, Celia and Peter, Anne and Simon.

    And these are given in the order of the weddings (starting with the earliest).

    The previous pairings were:

    Anne and Quentin
    Barbara and Peter
    Celia and Simon
    Dinah and Ronald
    Emily and Tristram

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: