Bridge Hands
August 11, 2015
This problem comes to us courtesy of The Awk Programming Language by Al Aho, Brian Kernighan and Peter Weinberger, where it appears as exercise 5-3. Their solution is on the next page. We represent the deck as an array of cards, with cards as integers from 51 (ace of spades) to 0 (deuce of clubs). We begin with a function that deals the deck and arranges the four hands in order:
(define (hands) (let loop ((deck (shuffle (range 52))) (hands (list))) (if (null? deck) hands (loop (drop 13 deck) (cons (sort > (take 13 deck)) hands)))))
The output of hands
contains the four hands in order North, West, East, South. Then we write a function that prints the formatted output:
(define (print-hands hands) (define (blanks n) (display (make-string n #\space))) (blanks 20) (display "NORTH") (newline) (blanks 20) (display (cards "S" (car hands))) (newline) (blanks 20) (display (cards "H" (car hands))) (newline) (blanks 20) (display (cards "D" (car hands))) (newline) (blanks 20) (display (cards "C" (car hands))) (newline) (set! hands (cdr hands)) (display "WEST") (blanks 36) (display "EAST") (newline) (display (cards "S" (car hands))) (blanks (- 40 (string-length (cards "S" (car hands))))) (display (cards "S" (cadr hands))) (newline) (display (cards "H" (car hands))) (blanks (- 40 (string-length (cards "H" (car hands))))) (display (cards "H" (cadr hands))) (newline) (display (cards "D" (car hands))) (blanks (- 40 (string-length (cards "D" (car hands))))) (display (cards "D" (cadr hands))) (newline) (display (cards "C" (car hands))) (blanks (- 40 (string-length (cards "C" (car hands))))) (display (cards "C" (cadr hands))) (newline) (set! hands (cddr hands)) (blanks 20) (display "SOUTH") (newline) (blanks 20) (display (cards "S" (car hands))) (newline) (blanks 20) (display (cards "H" (car hands))) (newline) (blanks 20) (display (cards "D" (car hands))) (newline) (blanks 20) (display (cards "C" (car hands))) (newline))
The cards
function returns a string containing the cards of the designated suit in the designated hand; it calls a function face
to convert the card index to a face value:
(define (cards suit hand) (define (between lo hi) (lambda (x) (<= lo x hi))) (cond ((string=? suit "S") (string-join #\space (cons "S:" (map face (filter (between 39 51) hand))))) ((string=? suit "H") (string-join #\space (cons "H:" (map face (filter (between 26 38) hand))))) ((string=? suit "D") (string-join #\space (cons "D:" (map face (filter (between 13 25) hand))))) ((string=? suit "C") (string-join #\space (cons "C:" (map face (filter (between 0 12) hand))))))) (define (face card) (case (modulo card 13) ((12) "A") ((11) "K") ((10) "Q") ((9) "J") (else (number->string (+ (modulo card 13) 2)))))
You can run the program at http://ideone.com/IcpYvT, where you will also see the contributions from the Standard Prelude. Here’s a sample run:
> (print-hands (hands)) 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
I have no direct experience teaching beginning programmers, but I suspect this would make a good assignment partway through a first programming course, as the imperative version of the program uses arrays, loops, random numbers and a little bit of arithmetic, data types for the cards, sorting, and formatted output, and requires no input. I know some of my readers do teach beginning programmers. What do you think?
In Python.
Good to see you recovered!
Hereby my Python solution..
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"))
@Paul, @Rutger: could you please tell me how do you insert your code in such a beauty way? Which website do you use?
@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.
@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.
@Paul Thanks it works fine!
A Haskell version.
[…] Bridge hands problem in C++ […]
[…] bridge hands problem on programming praxis in Common […]