Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
You have good points. I just find it odd that with everything under the sun, there isn't already one out there. With regards to your point on clarity and explanation - let me take this opportunity now to do so.

Precalculating Scores

When calculating points for sums of 15 you do not need to consider the suit of the card. You can also consider 10, Jack, Queen, and King as the same since they all have the value of 10. This means that there are only 1993 unique hands necessary to calculate any cribbage hand for 15s. I used a brute-force approach of summing all combinations of cards in group sizes of 2-5.

I then realized that if there was no card present that had a value of 10 (T/J/Q/K), I could also safely determine the points resulting from 2/3/4 of a kind. The reason the code works may not be obvious so I have included comments.

my %card; ++$card{$_} for @hand; $score += $_ * ($_ - 1) for values %card; # 1 * 0 = 0 (0 points for 1 of a kind) # 2 * 1 = 2 (2 points for 2 of a kind) # 3 * 2 = 6 (6 points for 3 of a kind) # 4 * 3 = 12 (12 points for 4 of a kind)

If you have more than 1 2 of a kind or 3/4 of a kind then you can't possibly have a flush. I added a flag if I knew it was safe not to check. You also can't possibly have right-jack if no card has a value of 10 - another flag.

I could also determine the value of any straights if no card had a value of 10. Since there are only 10 possible sequences of cards that can score points for a run, I avoided using loops. I am just going to explain the algorithm and hope that the code is clear as a result.

  • To be a run, each card must have a difference of 1 with its adjacent card
  • Sort the unique values in your hand
  • Determine the number of unique values
  • Check for possible runs of that size in descending order - end if none
  • Multiply the length of the run by the product of the count of cards at each position in the run

The hand, the flags, and the score are outputed in 8 bytes. 5 for the hand, 1 for the flags, and 2 for the score.

Calculate Total Score

The first step in calculating the total score is to convert the argument into the same format used to precalulate. We then lookup that hand and get back a 3 element array.

0 = calculated score so far 1 = flag indicating if any card has a value of 10 2 = flag indicating if it is necessary to check for flush

We know that we only have to check for 2/3/4 of a kind, straights, and right-jack if a card with the value of 10 is present. The method for determining 2/3/4 of a kind and straights has already been covered. To determine if we have right-jack:

# Find suits of any jack in the first 4 cards my %jack = map { $_ => 1 } substr($str, 0, 8) =~ /(?<=J)(.)/g; # Determine if the suit of the 5th card matches ++$score if $jack{ substr($str, -1, 1) };

Finally, we address potential flushes if necessary.

# Get the unique list of suits in the first 4 cards my %suit = map {$_ => undef} unpack('xAxAxAxA', $str); # If all the same, count 1 per card if (keys %suit == 1) { $score += 4; # If cut-card matches, add 1 for that too $score += 1 if substr($str, 1, 1) eq substr($str, -1, 1); }

I am not sure how fast this is compared to other approaches but I think it is a great start for someone interested in working on a Games::Cards::Cribbage.

Cheers - L~R

In reply to Re^2: RFC: Cribbage::Hand by Limbic~Region
in thread RFC: Cribbage::Hand by Limbic~Region

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others contemplating the Monastery: (5)
    As of 2018-04-19 21:45 GMT
    Find Nodes?
      Voting Booth?