Bridge Hands

August 11, 2015

[ Thanks to all who wrote with good wishes after my post last Friday. I am fully recovered and back at work. ]

Newspapers and textbooks often print bridge hands in the format shown below, then discuss the proper playing of the hand:

                    NORTH
                    S: A Q J 10 8
                    H: 5 4 2
                    D: 9
                    C: 10 7 6 2
WEST                                    EAST
S: 7                                    S: 6
H: Q J 7 6 3                            H: K 10 8
D: J 10 6 4 3                           D: A K Q 5
C: A 8                                  C: K 9 5 4 3
                    SOUTH
                    S: K 9 5 4 3 2
                    H: A 9
                    D: 8 7 2
                    C: Q J

Your task is to write a program to generate random bridge hands and print them in the format shown above. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

Pages: 1 2 3

10 Responses to “Bridge Hands”

  1. Paul said

    In Python.

    import random
    from itertools import groupby
    from operator import itemgetter
    
    VALUES = list("23456789TJQKA")
    VALUES[8] = "10"
    
    def random_hand():
        cards = list(range(52))
        random.shuffle(cards)
        return [sorted(cards[i*13:i*13+13], reverse=True) for i in range(4)]
     
    def nr_to_card(n):
        suit, value = divmod(n, 13)
        return "CDHS"[suit], VALUES[value]
    
    def hand(side):
        cards = [nr_to_card(c) for c in side]
        cc = groupby(cards, key=itemgetter(0))
        D = {k:"{:s}: {:s}".format(k, " ".join(v for s, v in g)) for k, g in cc}
        return [D[k] if k in D else k + ":" for k in "SHDC"]
        
    def print_bridge(hands):
        output = [[" "] * 80 for _ in  range(15)]
        pos = [(0, 20), (5, 0), (5, 40), (10, 20)]
        seats = ["NORTH", "WEST", "EAST", "SOUTH"]
        for (row, col), seat, hand_ in zip(pos, seats, hands):
            output[row][col:col+len(seat)] = seat
            for i, hi in enumerate(hand(hand_)):
                output[row+i+1][col:col+len(hi)] = hi
        for o in output:
            print ("".join(o))
            
    print_bridge(random_hand())
    
  2. Rutger said

    Good to see you recovered!
    Hereby my Python solution..

    import random
    
    suits = ["S", "H", "D", "C"]
    values = ["2","3","4","5","6","7","8","9","10","J","Q","K","A"]
    
    # returns tuples of (suit, value)
    def deck(shuffle=True):
        def card_number_to_card_tuple(n):
            suit, value = divmod(n, 13)
            return suits[suit], values[value]
    
        all_cards = range(52)
        if shuffle:
            random.shuffle(all_cards)
        return map(card_number_to_card_tuple, all_cards)
    
    # returns list of 4 hands, with each hand as a dict with k=suit , v=list of values for suit k
    def four_hands(deck):
        hands = []
        for hand in [deck[i*13:i*13+13] for i in range(4)]:
            d = dict(zip(suits, [[],[],[],[]]))
            for suit, value in hand:
                d.setdefault(suit, []).append(value)
            hands.append(d)
        return hands
     
    
    # prints output. Spent most time in that python format mini language..
    def print_formatted(four_hands):
        def hand_to_string(hand):
            return [suit + ': ' + " ".join(hand[suit]) for suit in suits]
    
        print ' '*20 + 'NORTH'
        for north in hand_to_string(four_hands[0]):
            print ' '*20 + north
        print '{:<40}{:}'.format('WEST', 'EAST')
        for west, east in zip(hand_to_string(four_hands[1]), hand_to_string(four_hands[2])):
            print '{:<40}{:}'.format(west, east)
        for south in hand_to_string(four_hands[3]):
            print ' '*20 + south
    
    
    print_formatted(four_hands(deck()))
    
  3. Andras said

    Scala:
    import scala.util.Random
    type Card = Tuple2[String, String]
    val color: Seq[String] = List(“S”, “H”, “D”, “C”)
    val numbers: Seq[String] = (2 to 10 map { _.toString }) ++ List(“J”, “Q”, “K”, “A”)
    def numberSorter(a: String, b: String): Boolean = numbers.indexOf(a) > numbers.indexOf(b)
    val cards: Seq[Card] = Random.shuffle(for (c <- color; n List(filter(x, “S”), filter(x, “H”), filter(x, “D”), filter(x, “C”)))
    val blockLines = blocks.map(x => (List(x._1) ++ x._2).map(x => x + ” ” * (20 – x.length())))
    val north = for (i <- 0 to 4) yield " " * 20 + blockLines(0)(i) + " " * 20
    val west_east = for (i <- 0 to 4) yield blockLines(1)(i) + " " * 20 + blockLines(2)(i)
    val south = for (i <- 0 to 4) yield " " * 20 + blockLines(3)(i) + " " * 20
    println((north ++ west_east ++ south).mkString("\r\n"))

  4. Andras said

    @Paul, @Rutger: could you please tell me how do you insert your code in such a beauty way? Which website do you use?

  5. Paul said

    @Andras.I am using method Third as mentioned in the “Howto: Posting Source Code”. You have to know the mnemonic for Scala (I guess it is scala). Further the tag is usefull if you want to use a link in your post. I hope this helps.

  6. Paul said

    @Andras, the “a href” tag messed up part of my reply. You only have to google for this tag and see how it is used.

  7. Andras said

    @Paul Thanks it works fine!

  8. Globules said

    A Haskell version.

    import Data.Function (on)
    import Data.List (groupBy, intercalate, sortOn)
    import Data.List.Split (chunksOf)
    import Data.Maybe (fromMaybe)
    import Data.Ord (Down(..))
    import System.Random
    import System.Random.Shuffle (shuffle')
    import Control.Monad (liftM)
    
    shuffle :: (RandomGen r) => [a] -> r -> [a]
    shuffle xs = shuffle' xs (length xs)
    
    -- A standard deck of 52 cards, where each card is a pair consisting of a suit
    -- and a rank.
    deck :: [(Int, Int)]
    deck = [(s, r) | s <- [0..3], r <- [0..12]]
    
    -- Deal hands of 13 cards.  Each hand consists of ordered lists of ranks grouped
    -- by suit.
    deal :: [(Int, Int)] -> [[(Int, [Int])]]
    deal = map (map suitify . groupBy ((==) `on` fst) . sortOn Down) . chunksOf 13
      where suitify (rss@((r, _) : _)) = (r, map snd rss)
    
    showSuit :: Int -> String
    showSuit = (["S", "H", "D", "C"] !!)
    
    showRank :: Int -> String
    showRank = (ranks !!)
      where ranks = [ "2", "3",  "4", "5", "6", "7",
                      "8", "9", "10", "J", "Q", "K", "A"]
    
    -- Each element of the result is one suit letter followed by the card ranks.
    showHand :: [(Int, [Int])] -> [String]
    showHand cs = map (\s -> showSuit s ++ ": " ++ showRanks (ranks s)) [0..3]
      where ranks s = fromMaybe [] $ lookup s cs
            showRanks = unwords . map showRank
    
    printHand :: [String] -> IO ()
    printHand = putStrLn . intercalate "\n"
    
    -- Pad all the strings to the length of the longest.
    padR :: [String] -> [String]
    padR xs = let maxLen = maximum $ map length xs
              in map (padTo maxLen) xs
      where padTo mx s = s ++ replicate (mx - length s) ' '
    
    -- Prepend all the strings with spaces.
    padL :: Int -> [String] -> [String]
    padL n = map (replicate n ' ' ++)
    
    -- Append corresponding elements of the lists.
    followedBy :: [[a]] -> [[a]] -> [[a]]
    followedBy = zipWith (++)
    
    main :: IO ()
    main = do
      hands <- liftM (map showHand . deal . shuffle deck) getStdGen
      let [n, s, e, w] = zipWith (:) ["NORTH", "SOUTH", "EAST", "WEST"] hands
      printHand $ padL 20 n
      printHand $ padR w `followedBy` padL 30 e
      printHand $ padL 20 s
    
    $ ./bridge 
                        NORTH
                        S: K Q 9 5
                        H: Q 10
                        D: K 9 8 3
                        C: 6 5 4
    WEST                                     EAST
    S: A 10 8 7                              S: J 6 3
    H: K 8 2                                 H: J 9 7 6 3
    D: 6 4                                   D: Q J 7
    C: 9 8 3 2                               C: A Q
                        SOUTH
                        S: 4 2
                        H: A 5 4
                        D: A 10 5 2
                        C: K J 10 7
    
  9. […] Bridge hands problem in C++ […]

  10. […] bridge hands problem on programming praxis in Common […]

Leave a Reply

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 )

Facebook photo

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

Connecting to %s

%d bloggers like this: