Enigmatic Code

Programming Enigma Puzzles

Tantalizer 50: Bocardo pairs

From New Scientist #599, 30th May 1968 [link]

Here is a small puzzle based on a pack of cards and invented by Barbara Bocardo, the well-known lady logician. We start with a definition of what she calls a “Bocardo Pair”.

Two cards form a Bocardo Pair if and only if they either are neighbours in the same suit (e.g. 10 and Jack of clubs) or are of the same value and in neighbouring suits (e.g. the Jacks of clubs and diamonds). Aces are neighbours of Kings but not of twos. Spades are neighbours of both hearts and clubs and the order of suits (as in bridge) is clubs, diamonds, hearts, spades.

She explains all this with the help of an ordinary pack, which forms 26 Bocardo Pairs. She then removes the Queen of spades and four of diamonds from the pack. The puzzle is to work out whether the remaining 50 cards will make 25 Bocardo Pairs.

What is the answer and why?

This puzzle also appears in the book Tantalizers (1970).

[tantalizer50]

3 responses to “Tantalizer 50: Bocardo pairs

  1. Jim Randell 23 May 2024 at 9:14 am

    This Python program makes an adjacency matrix for the cards in a standard deck. (i.e. which cards can be paired with each other).

    It then tries to form a standard pack into pairs, and a modified pack into pairs, with no cards left over. (The runtime depends on how the cards are chosen, but both PyPy and recent version of CPython 3 have dictionaries that remember insertion order, and this gives a reasonable runtime).

    It runs in 118ms. (Internal runtime is 39ms).

    Run: [ @replit ]

    from enigma import (cproduct, peek, remove, append, printf)
    
    # values/suits
    (values, suits) = ('23456789XJQKA', 'CDHS')
    
    # construct adjacency matrix
    adj = dict()
    for ((i, v), (j, s)) in cproduct(enumerate(xs) for xs in [values, suits]):
      vs = list()
      if v != '2': vs = append(vs, values[i - 1] + s)
      if v != 'A': vs = append(vs, values[i + 1] + s)
      vs = append(vs, v + suits[(j - 1) % 4], v + suits[(j + 1) % 4])
      adj[v + s] = vs
    
    # make pairs from a pack
    def pairs(pack, ps=[]):
      # are we done?
      if not pack:
        yield ps
      else:
        # pick a card, any card
        x = peek(pack)
        # and consider adjacent cards
        for y in adj[x]:
          if y in pack:
            yield from pairs(remove(pack, x, y), append(ps, (x, y)))
    
    # find an example pairing up
    make_pairs = lambda pack: peek(pairs(pack), default=None)
    
    # start with a standard pack
    pack = list(adj.keys())
    # can we form it into pairs?
    ps = make_pairs(pack)
    printf("standard pack -> {ps}")
    
    # modify the pack
    pack = remove(pack, 'QS', '4D')
    # can we form it into pairs?
    ps = make_pairs(pack)
    printf("modified pack -> {ps}")
    

    Solution: No, the remaining cards cannot be formed into pairs.


    If we score the cards according to their values 2 – 14 (J=11, Q=12, K=13, A=14), and score the suits from 1 (clubs) – 4 (spades), then we can score a card by summing the score for the value and for the suit.

    And we note that when cards are paired their scores have different parity.

    However the scores of QS = 12+4 = 16 and 4D = 4+2 = 6 both have even parity, so when they are removed, we are left with 26 odd cards and only 24 even cards to pair them with, hence the pairing fails.

  2. Lise Andreasen 24 May 2024 at 12:53 am

    Putting the cards out on a table would be like:

    AKQJ098765432
    AKQJ098765432
    AKQJ098765432
    AKQJ098765432

    Removing the mentioned cards would be like:

    AKQJ098765432
    AKQJ098765 32
    AKQJ098765432
    AK J098765432

    Color these cards like a chess board. Ace of clubs white, king of clubs black, ace of diamonds black etc.

    Each Bocardo Pair has one black and one white card.

    The removed cards have the same color.

    Hence 25: pairs won't be possible.

Leave a Comment

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