[SUMMARY] Euchre Hands (#55)

Discussion in 'Ruby' started by Ruby Quiz, Nov 24, 2005.

  1. Ruby Quiz

    Ruby Quiz Guest

    My wife can't stand how Euchre reorders the suits. "Everyone know Jacks come
    after Tens," she would say. Funny how most of us except the odd Ace concept
    where the low card is frequently the high card, or even both. Once you start
    moving Jacks though, a lot of people have trouble following the game.

    Of course, my wife would also say, "How can you call that Jack a Club (assuming
    Clubs are Trump), when it has Spades printed on it?" She's got me there.

    My wife's analysis of Euchre's card order is really right on: It's unusual.
    Because of that, the traditional sort() tool won't get you all the way to a
    solution. That makes us think about other options.

    Don't get me wrong, many solutions bent sort() to their will. However, as I
    said in the quiz, I was looking as much at how to know the answer is correct as
    I was at just having an answer. To me, the weighted sorts are hard to prove and
    no one did it to my satisfaction. Given that, I want to look at the other major
    approach people hit on.

    The following is the beginning of Bob Showalter's solution:

    #!/usr/local/bin/ruby -w

    # Euchre hand sorter

    CARDS = %w(A K Q J T 9)
    suits = %w(Spades Hearts Clubs Diamonds)

    # read and check input data
    trump = gets.chomp
    raise "Invalid Trump Suit" unless suits.include? trump
    hand = []
    5.times do
    card = gets.chomp
    raise "Invalid card #{card}" unless
    card.length == 2 &&
    CARDS.include?(card[0,1]) &&
    suits.find { |suit| suit[0,1].downcase == card[1,1] }
    raise "Duplicate card #{card}" if hand.include? card
    hand << card
    end

    # ...

    Bob begins by defining the traditional card order, and the four suits.

    The next chunk of code reads the trump suit and hand into variables. This code
    is careful to ensure proper input. Suits must be one of the known four and
    cards must be two characters, have a known face and suit, and not be duplicated.

    # ...

    # rotate trump suit to front
    suits.push(suits.shift) while suits.first != trump

    # if hand is void in second suit, swap second and fourth
    # (this keeps output in alternating colors)
    unless hand.find { |card| card[1,1] == suits[1][0,1].downcase }
    suits[1], suits[3] = suits[3], suits[1]
    end

    # ...

    This chunk of code does two things. First, the suits are "rotated" until trump
    is the first suit. Note that this is why "CARDS" was declared as a constant but
    "suits" is just a variable. Good hints for the reader in this code.

    The second thing the code does is the trick many hit on to defeat my extra
    red/black requirement. If we have four suits ordered red, black, red, black (or
    black, red, black, red), the only edge case we can do anything about is when the
    player doesn't have the second suit. Here's the mapping of possible orderings
    (assuming Spades is trump) to show what I mean:

    all four suits (black, red, black, red ordering works fine)

    Spades, Hearts, and Clubs (already correct)
    Hearts, Clubs, and Diamonds (already correct)
    Spades, Hearts, and Diamonds (can't move trump to fix)
    Spades, Clubs, and Diamonds (the fixable case)

    just two suits (moves won't change anything)
    a single suit (already correct)

    In the fixable case, swapping the (missing) second and (present) fourth suits
    resolves the issue. That's what you're seeing in the code above.

    # ...

    # generate a sort order
    deck = []
    suits.each do |suit|
    CARDS.each do |card|
    deck << card + suit[0,1].downcase
    end
    end

    # ...

    Given that the correct suit order has been established, the entire Euchre deck
    is built, in traditional card order.

    # ...

    # move bowers to front
    deck.insert(0, deck.delete_at(3))
    deck.insert(1, deck.delete_at(15))

    # ...

    With the full deck in proper suit order, the only thing that remains is to shift
    the bowers to the head of the pack. Their location is assured, thus the use of
    magic numbers above, though index() is an alternative.

    # ...

    # output sorted hand (n.b. Array#& (intersection) seemed to work, but
    # is the order guaranteed?)
    puts trump
    puts deck.select { |card| hand.include? card }

    With the work out of the way, showing the results is trivial. Print trump and
    then just walk the deck printing any card in the hand.

    I think that solution is very straight-forward and easy to accept as correct,
    even without a large group of tests. Let's look at one more variation of the
    same theme, by Dominik Bathon:

    order = {
    "Spades" => "JsJcAsKsQsTs9sAdKdQdJdTd9dAcKcQcTc9cAhKhQhJhTh9h",
    "Hearts" => "JhJdAhKhQhTh9hAsKsQsJsTs9sAdKdQdTd9dAcKcQcJcTc9c",
    "Clubs" => "JcJsAcKcQcTc9cAhKhQhJhTh9hAsKsQsTs9sAdKdQdJdTd9d",
    "Diamonds" => "JdJhAdKdQdTd9dAcKcQcJcTc9cAhKhQhTh9hAsKsQsJsTs9s"
    }

    trump = gets.strip
    cards = readlines.map { |l| l.strip }
    o = order[trump].dup
    # do we have a card of the 2nd suit
    unless cards.any? { |card| card[1] == o[15] }
    # if not replace second suit by the last
    o[14, 12] = o[36, 12]
    end
    puts trump, cards.sort_by { |card| o.index(card) }

    This is basically the same thing, with prebuilt decks. The code here just
    selects which of the four possible decks to use base on the trump indication in
    the input.

    Again we see the second and fourth suits swapped, if needed. This time it is
    done with a simple String copy.

    Finally, cards are sorted, by their position in the complete deck.

    My thanks to all the card sharks who solved the quiz and even taught me
    alternate hand ordering schemes.

    Tomorrow we're off to the Pinewood Derby, so everyone pick up a car kit sometime
    this evening...
    Ruby Quiz, Nov 24, 2005
    #1
    1. Advertising

  2. Ruby Quiz wrote:
    >
    > # rotate trump suit to front
    > suits.push(suits.shift) while suits.first != trump
    >
    >
    > ...First, the suits are "rotated" until trump
    > is the first suit. Note that this is why "CARDS" was declared as a constant but
    > "suits" is just a variable. Good hints for the reader in this code.


    Having much to learn, I have since discovered that it works fine even if
    SUITS is declared as a constant. You only get a warning if you reassign
    something else to SUITS; you can maniuplate the array that SUITS
    references without getting a warning.
    Bob Showalter, Nov 24, 2005
    #2
    1. Advertising

  3. Ruby Quiz

    James Gray Guest

    Re: Euchre Hands (#55)

    bob_showalter wrote:
    >
    > Having much to learn, I have since discovered that it works fine even if
    > SUITS is declared as a constant. You only get a warning if you reassign
    > something else to SUITS; you can maniuplate the array that SUITS
    > references without getting a warning.


    Yes, but I think it was more correct as is, since it showed that it was
    a variable and could change.

    James Edward Gray II

    --
    Posted via http://www.ruby-forum.com/.
    James Gray, Nov 24, 2005
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. xfairguy
    Replies:
    4
    Views:
    386
  2. Ruby Quiz

    [QUIZ] Euchre Hands (#55)

    Ruby Quiz, Nov 18, 2005, in forum: Ruby
    Replies:
    5
    Views:
    144
    Timothy Goddard
    Nov 21, 2005
  3. Robin Stocker

    [QUIZ SOLUTION] Euchre Hands (#55)

    Robin Stocker, Nov 20, 2005, in forum: Ruby
    Replies:
    26
    Views:
    241
    Zed Lopez
    Nov 23, 2005
  4. Daniel Sheppard

    [QUIZ SOLUTION] Euchre Hands (#55)

    Daniel Sheppard, Nov 21, 2005, in forum: Ruby
    Replies:
    0
    Views:
    96
    Daniel Sheppard
    Nov 21, 2005
  5. Warren Brown

    [SOLUTION] Euchre Hands (#55)

    Warren Brown, Nov 21, 2005, in forum: Ruby
    Replies:
    2
    Views:
    92
    James Edward Gray II
    Nov 23, 2005
Loading...

Share This Page