Enigmatic Code

Programming Enigma Puzzles

Enigma 493b: Christmas cards

From New Scientist #1644, 24th December 1988 [link]

The five couples in Yuletide Close send cards to some of their neighbours. Some of them told me who (apart from themselves) send cards.

Alan: “The cards not involving us are the ones exchanged between Brian’s and Charles’s houses, the ones exchanged between Brian’s and Derek’s, the card from Charles to Derek (or the other way round, I’m not sure which) and the card from Brian to Eric (or the other way round).”

Brenda: “Apart from our cards, Alice and Emma exchange cards, as do Dawn and Christine, and Dawn sends Emma one.”

The Smiths: “The cards not involving us are the ones exchanged by the Thomases and the Unwins, those exchanged by the Williamses and the Vincents, the one from the Thomases to the Williamses and one between the Unwins and the Vincents (but I forget which way).”

No 3: “Nos 1 and 5 exchange cards, one card passes between Nos 2 and 4 (I don’t know which way) and No 2 sends one to No 1.”

Charles Thomas receives the same number of cards as he sends. On Christmas Eve, he goes on a round tour for drinks. He delivers one of his cards, has a drink there, takes one of their cards and delivers it, has a drink there, takes one of their cards and delivers it, has a drink there, takes one of their cards and delivers it, has a drink there, collects the card from them to him and returns home, having visited every house in the close.

Name the couples at 1-5 (for example: 1, Alan and Brenda Smith; 2, …).

Enigma 1321 is also called “Christmas cards”.

This completes the archive of Enigma puzzles from 1988. There is now a complete archive from the start of Enigma in 1979 to the end of 1988, and also from February 1999 to the final Enigma puzzle at the end of 2013. There are 1265 Enigma puzzles posted to the site, which is around 70.8% of all Enigma puzzles published.

[enigma493b] [enigma493]

One response to “Enigma 493b: Christmas cards

  1. Jim Randell 1 April 2019 at 8:42 am

    This Python program runs in 100ms.

    Run: [ @repl.it ]

    from itertools import product, permutations
    from enigma import irange, icount, seq_all_same, tuples, printf
    
    # houses
    houses = irange(1, 5)
    
    # m records who sends cards to who
    # m[(x, y)] = True; if x sends a card to y
    #           = False; if x does not send a card to y
    #           = None; if currently unknown
    m0 = dict(((x, y), None) for (x, y) in product(houses, repeat=2) if x != y)
    
    # update map m, for keys not involving x, according to vs
    # return a new map, or None
    def update(m, x, vs):
      m1 = m.copy()
      for (k, v) in m.items():
        if x in k: continue
        u = (k in vs)
        if v is None:
          m1[k] = u
        else:
          if v != u: return None
      return m1
    
    # house number 3 gives the following information
    # for cards not involving house 3
    vs1 = set([(1, 5), (5, 1), (2, 1)])
    for vs in [[(2, 4)], [(4, 2)]]:
      m1 = update(m0, 3, vs1.union(vs))
      if m1 is None: continue
    
      # assign females to the houses
      for (fA, fB, fC, fD, fE) in permutations(houses):
    
        # fB gives information about all cards not invloving fB
        vs2 = set([(fA, fE), (fE, fA), (fD, fC), (fC, fD), (fD, fE)])
        m2 = update(m1, fB, vs2)
        if m2 is None: continue
    
        # assign surnames to the houses
        for (S, T, U, V, W) in permutations(houses):
    
          # S gives information about all cards not involving S
          vs3 = set([(T, U), (U, T), (W, V), (V, W), (T, W)])
          for vs in [[(U, V)], [(V, U)]]:
            m3 = update(m2, S, vs3.union(vs))
            if m3 is None: continue
    
            # assign males to the houses
            for (mA, mB, mC, mD, mE) in permutations(houses):
    
              # make sure there is someone called "Charles Thomas"
              if not(mC == T): continue
    
              # mA gives information about all cards not involving mA
              vs4 = set([(mB, mC), (mC, mB), (mB, mD), (mD, mB)])
              for vs in product([(mC, mD), (mD, mC)], [(mB, mE), (mE, mB)]):
                m4 = update(m3, mA, vs4.union(vs))
                if m4 is None: continue
    
                # make sure Mr Thomas sends and receives the same number of cards
                if not seq_all_same(icount(k for (k, v) in m4.items() if k[i] == T and v) for i in (0, 1)): continue
    
                # choose an order for Mr Thomas's walk
                for w in permutations(houses):
                  # he starts at his own house
                  if not(w[0] == T): continue
                  # and there is a corresponding chain of cards
                  if not all(m4[k] for k in tuples(w + w[:1], 2)): continue
    
                  printf("f={f}, m={m}, s={s}, w={w}", f=(fA, fB, fC, fD, fE), m=(mA, mB, mC, mD, mE), s=(S, T, U, V, W))
    

    Solution: The residents of the close are:

    1: Alan and Christine, Williams
    2: Charles and Brenda, Thomas
    3: Brian and Emma, Unwin
    4: Derek and Alice, Smith
    5: Eric and Dawn, Vincent

    The card exchanges are (3 bidirectional, 3 unidirectional):

    1 ↔ 5
    2 ↔ 3
    3 ↔ 4
    2 → 1
    4 → 2
    5 → 3

    Charles’s walk is: 2 → 1 → 5 → 3 → 4 → 2.

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: