• Posts
  • RSS
  • ◂◂RSS
  • Contact

  • Absolutely Winning Bridge Hands

    December 24th, 2019
    games  [html]
    In bridge the best you can do is commit to take all the cards and then follow through. Even better if you do this without the help of a trump suit. Playing today I was curious: what fraction of hands are "absolutely winning" for 7NT, in that they'll let you make this contract no matter what your partner or opponents happen to hold?

    Here's one example hand:

    • Clubs: A, K, Q
    • Diamonds: A, K, Q
    • Hearts: A, K, Q
    • Spades: A, K, Q, J

    And here's a very different example:

    • Clubs: A
    • Diamonds: A
    • Hearts: A
    • Spades: A, K, Q, J, 10, 9, 8, 7, 6, 5

    Any absolutely winning 7NT hand needs to have all the aces, so that whatever your opponent leads you can take the first trick. Then all the other cards need to be "good", in that no other player can have a higher card in their suit.

    Since a card being "good" requires that you also have every higher card in the same suit, all that matters for each suit is its length. If I tell you that an absolutely winning hand has four spades, you know they are A, K, Q, J. What we're doing, then, is assigning positive lengths to suits, where all lengths must sum to 13. But it's simpler if we ignore the aces, since you have to have all four, and assign non-negative lengths that add to 9. How many ways can we do this?

    Since I'm more of a programmer than a mathematician, here's a way to solve this with code:

    print(len([
      (c, d, h, s)
      for c in range(10)
      for d in range(10 - c)
      for h in range(10 - c - d)
      for s in range(10 - c - d - h)]))
    

    Which gives 715. [1] There are 52-choose-13 bridge hands (about 635B) so your chances of getting an absolutely winning 7NT hand is 715 in 635B or just a bit better than one in a billion.

    While very unlikely, this is in the "it could happen, maybe" range and not all the way to "no way, unless the shuffle was rigged".

    Update 2019-12-25: the above is wrong in two ways. First, the number of spades is completely determined by the number of the other three suits, and so for s in range(10 - c - d - h) should not have been included. And second, if you have seven or more of a suit then which lowest cards you have doesn't matter, because by the time you get to them no one else will have any of the suit. Here's a revised solution that fixes these two:

    from math import factorial
    
    def choose(n, r):
      return factorial(n) // factorial(r) // factorial(n-r)
    
    count = 0
    
    # Start by choosing a length for each suit.
    # Most lengths will lead to one valid
    # combination, though a few will lead to
    # several.
    
    # Since every suit needs to have an ace,
    # there are nine remaining cards in the hand
    # to be divided among the four suits.
    hand_size_ignoring_aces = 9
    
    for c in range(hand_size_ignoring_aces + 1):
      for d in range(hand_size_ignoring_aces + 1 - c):
        for h in range(hand_size_ignoring_aces + 1 - c - d):
          s = hand_size_ignoring_aces - c - d - h
    
          # If a suit has >= 7 cards there are
          # extra possibilities: 
          #   A K Q J followed by any 5 others.
          # If your suit is length N, you need
          # the top 13-N cards in order, and
          # then any remaining cards in that
          # suit are also good because no one
          # else has that suit
    
          # At most one suit can have >= 7 since
          # you have 13 total, so find out if
          # we're in this case.
          longest = max(c,d,h,s)
    
          # We excluded the aces, but it's
          # clearer here with them included:
          longest += 1
    
          if longest < 7:
            # Situation doesn't apply, we must
            # just have the top cards in the
            # suit in order
            count += 1
          else:
            others_have = 13 - longest
            in_order = others_have
            out_of_order = longest - in_order
            count += choose(
              others_have + out_of_order,
              out_of_order)
    print(count)
    

    This gives 3,756 hands, or about six in a billion.


    [1] This is 13-choose-4, and while there's probably an obvious-in-retrospect reason why, I'm not seeing it.

    Comment via: facebook, lesswrong

    Recent posts on blogs I like:

    Fireside Friday, November 27, 2020

    Hey folks! Fireside this week. A bit of a change-up in terms of the coming attractions. I had planned to start “Textiles, How Did They Make It?” next, but I want to do a bit more reading on some of the initial stages of textile production (that is, the pr…

    via A Collection of Unmitigated Pedantry November 27, 2020

    Building Depth and Window Space

    How much window space does an apartment need, relative to its area, and how does this affect building style? A fascinating post from about a year ago on Urban Kchoze makes the argument that modern North American buildings are too deep – Simon calls them o…

    via Pedestrian Observations November 27, 2020

    Thoughts you mightn't have thunk about remote meetings

    Welcome to this week's edition of "building a startup in 2020," in which all your meetings are suddenly remote, and you probably weren't prepared for it. I know I wasn't. We started a "fully remote" company back in 2019, but …

    via apenwarr November 23, 2020

    more     (via openring)


  • Posts
  • RSS
  • ◂◂RSS
  • Contact