Enigmatic Code

Programming Enigma Puzzles

Tantalizer 476: Take your partners

From New Scientist #1027, 18th November 1976 [link]

Amble, Bumble, Crumble and Dimwit had a jolly night of it at the Old Tyme ball. Each took his wife but did not dance with her. In fact each danced only three dances, changing partner each time, and spent the rest of the night in the bar.

In the Cha-Cha Amble danced with a wife larger than Mrs A and Bumble with a wife larger than Mrs B. Then came the rumba, with Crumble in the arms of a wife larger than Mrs C. Then they did the tango, in which Bumble had a wife smaller than Mrs B and Mrs B was squired by a man fatter than Amble. These were the three dances mentioned and no two men swapped partners [with each other] between the Cha-Cha and the rumba or between the rumba and the tango. No two wives are the same size.

What were the pairings for the rumba?

[tantalizer476]

Advertisements

2 responses to “Tantalizer 476: Take your partners

  1. Jim Randell 2 August 2017 at 8:11 am

    Unless I’ve missed something I think this puzzle is flawed. I get three possible scenarios that satisfy the conditions given.

    This Python program runs in 47ms.

    from itertools import permutations, combinations
    from enigma import join, printf
    
    # choose partners from s that aren't already allocated in ps
    def choose(s, *ps):
      for r in permutations(s):
        if any(any(r[i] == n for (i, n) in enumerate(p)) for p in ps): continue
        yield r
    
    # choose an order for size (smallest to largest)
    for s in permutations('ABCD'):
      # size maps name -> measure
      size = dict((n, i) for (i, n) in enumerate(s))
    
      # choose partners for A
      for A in choose('BCD'):
    
        # dance 1: "A's partner was larger than Mrs A"
        if not(size[A[0]] > size['A']): continue
        # dance 3: "Mrs B's partner was fatter than A"
        if A[2] == 'B': continue
    
        # choose partners for B
        for B in choose('ACD', A):
    
          # dance 1: "B's partner was larger than Mrs B"
          if not(size[B[0]] > size['B']): continue
          # dance 3: "B's partner was smaller than Mrs B"
          if not(size[B[2]] < size['B']): continue
    
          # choose partners for C
          for C in choose('ABD', A, B):
    
            # dance 2: "C's partner was larger than Mrs C"
            if not(size[C[1]] > size['C']): continue
    
            # partners for D
            for D in choose('ABC', A, B, C):
    
              # determine the partners in each dance
              p = list(zip(A, B, C, D))
    
              # no partners are swapped in pairs between dance 1 and dance 2
              # nor between dance 2 and dance 3
              if any(
                (p[0][x] == p[1][y] and p[1][x] == p[0][y]) or
                (p[1][x] == p[2][y] and p[2][x] == p[1][y])
                for (x, y) in combinations((0, 1, 2, 3), 2)
              ): continue
    
              # output solution
              f = join
              printf("rumba = {r} [size={s}, A={A} B={B} C={C} D={D}]", r=f(p[1]), s=f(s), A=f(A), B=f(B), C=f(C), D=f(D))
    

    The wives, in size order (smallest to largest) are:

    [w1] = Mrs A < Mrs C < Mrs B < Mrs D
    [w2] = Mrs C < Mrs A < Mrs B < Mrs D

    And the partners in the dances are:

    [p1] =

    Dance 1: A & Mrs B, B & Mrs D, C & Mrs A, D & Mrs C
    Dance 2: A & Mrs D, B & Mrs C, C & Mrs B, D & Mrs A
    Dance 3: A & Mrs C, B & Mrs A, C & Mrs D, D & Mrs B

    [p2] =

    Dance 1: A & Mrs C, B & Mrs D, C & Mrs B, D & Mrs A
    Dance 2: A & Mrs B, B & Mrs A, C & Mrs D, D & Mrs C
    Dance 3: A & Mrs D, B & Mrs C, C & Mrs A, D & Mrs B

    The valid combinations that provide a solution being:

    [w1]+[p1]
    [w1]+[p2]
    [w2]+[p1]

    Which gives two possible answers for the pairings of the rumba (Dance 2). We can write them as (A D) (B C) from [p1] and (A B) (C D) from [p2].

    The published solution corresponds to [p1], and the stated order for the wives is [w2].

    We could rescue the puzzle by adding the following text before the final question:

    “If I told you the relative sizes of the wives you would be able to work out who danced with who.”

    Then we would know for sure that the sizes of the wives must be [w2] and the partners [p1], giving the following answer:

    Solution: In the rumba Amble danced with Mrs Dimwit, and Dimwit danced with Mrs Amble. Bumble danced with Mrs Crumble, and Crumble danced with Mrs Bumble.

  2. Brian Gladman 2 August 2017 at 11:39 pm

    My solution matches Jim’s so I agree that the puzzle is flawed.

    from itertools import combinations, permutations
    
    # print header for the output
    hdr = True
    print(' ' * 25 + 'ChaCha:       Rumba:        Tango:')
    print(' ' * 16 + '--men--> (A, B, C, D), (A, B, C, D), (A, B, C, D)')
    
    # permute wives to give their size order
    for ws in permutations('ABCD'):
      
      # permute wives for the Cha-Cha
      for wc in permutations('ABCD'):
        
        # no-one dances with their own wife
        if any(x == y for x, y in zip('ABCD', wc)):
          continue
        # A and B dance with ladies larger than their wives
        if any(ws.index(wc[x]) <= ws.index(y) for x, y in zip((0, 1), 'AB')):
          continue
        
        # permute wives for the Rumba
        for wr in permutations('ABCD'):
    
          # no-one dances with their own wife
          if any(x == y for x, y in zip('ABCD', wr)):
            continue
          # C dances with a lady larger than his wife
          if ws.index(wr[2]) <= ws.index('C'):
            continue
          
          # all pairs change partners
          if any(x == y for x, y in zip(wc, wr)):
            continue
          # no two husbands swap partners between the Cha-Cha and the Rumba
          if any((wr.index(x), wr.index(y)) == (wc.index(y), wc.index(x)) 
                                        for x, y in combinations('ABCD', 2)):
            continue
          
          # permute wives for the Tango
          for wt in permutations('ABCD'):
      
            # no-one dances with their own wife
            if any(x == y for x, y in zip('ABCD', wt)):
              continue
            # B dances with a lady smaller than his wife and wife B doesn't
            # dance with A
            if ws.index(wt[1]) >= ws.index('B') or wt.index('B') == 0:
              continue
            
            # all pairs change partners again
            if any(any(x == y for x, y in zip(w, wt)) for w in (wc, wr)):
              continue
            # no two husbands swap partners between the Rumba and the Tango
            if any((wt.index(x), wt.index(y)) == (wr.index(y), wr.index(x)) 
                                          for x, y in combinations('ABCD', 2)):
              continue
            # output the wives in order of size and the men's (A, B, C, D)
            # partners in the ChaCha, the Rumba and the Tango respectively
            dc, dr, dt = ', '.join(wc), ', '.join(wr), ', '.join(wt)
            print(f"({' < '.join(ws)}) -women-> ({dc}), ({dr}), ({dt})")
    

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

%d bloggers like this: