Proposed Hint/Solution suggestion - Poker Hands

After solving this problem I was curious to see if it differed much from the solution in the hint, to find there was no solution there. So I thought I would share mine in case someone would like to put it there.

What is your hint or solution suggestion?

Problem Explanation:

  • In this challenge you need to supply a function that accepts an array of poker card hands, and returns a sum of how many of those hands player 1 wins
  • The array contains strings, each string containing 10 playing card indicators, the first 5 for Player 1, the next 5 for Player 2
  • The function needs to analyze those hands, and determine if Player 1 is the winner, and tally how many of the hands supplied in the array were won by Player 1

Proposed Solution:

Summary
function pokerHands(arr) {

  // Initialize Variables
  let cardValues = {2:2, 3:3, 4:4, 5:5, 6:6, 7:7, 8:8, 9:9, T:10, J:11, Q:12, K:13, A:14}
  let winsP1 = 0;
  let handP1, handP2;
  let scoreP1, scoreP2;

  // For each hands in the provided array input, analyze winner
  for (let hands of arr) {

    // Split input into two separate hands
    handP1 = hands.split(" ");
    handP2 = handP1.splice(5,5);

    // Calculate score for each players hand
    scoreP1 = calcHand(handP1);
    scoreP2 = calcHand(handP2);
    
    // Check values of the score array to check for player 1 win
    for (let x in scoreP1) {
      if (scoreP1[x] > scoreP2[x]) {
        winsP1++;
        break;
      } else if (scoreP2[x] > scoreP1[x]) {
        break;
      }
    }
  }

  // Return sum of all the games player one won
  return winsP1;


//---- function calcHand - Analyizes supplied card hand and return score array ------------------------
  function calcHand (theHand) {
    // Will hold counts of suits and cards in the hand Ex: {14: 4, 11: 1} = 4 aces and 1 jack
    let suits = {}, cards = {};

    // Score [hand score, major high card, minor high card, next highest, next highest, next highest]
    let score = [0,0,0,0,0,0]  

    // Count card types and suit types in the hand, convert card type to integer
    for (let card of theHand) {
      cards[cardValues[card[0]]] = (cards[cardValues[card[0]]] + 1) || 1;
      suits[card[1]] = (suits[card[1]] + 1) || 1;
    }
    
    // Get the length of card and suit objects
    let cardLen = Object.keys(cards).length;
    let suitLen = Object.keys(suits).length;

    // If 5 different cards present - its a straight or high card, and possible flush
    if (cardLen == 5) {   

      // Sort card types in descending order  
      let cardNums = Object.keys(cards).map(item => parseInt(item));
      cardNums.sort( (a,b) => b-a );

      //If straight detected (highest - lowest cards = 4), return score of 5, with card values attached, or 1 for high card
      if (cardNums[0] - cardNums[4] == 4) {
        score = [5].concat(cardNums);
      } else {
        score = [1].concat(cardNums);
      }

      // If flush (only one suit present), adjust score accordingly
      if (suitLen == 1) { 
        score[0] += 5;  //( so 6 for flush, 10 for straight flush)
      }  
    }

    // If 2 different card types - its a four of a kind or full house
    if (cardLen == 2) {

      let twoCards = Object.keys(cards);
      switch(cards[twoCards[0]]) {
        // if card counts are 1 or 4, its 4 of a kind, put the 4 card as major, 1 card as minor
        case 1: score = [8, twoCards[1], twoCards[0], 0, 0, 0];break;
        case 4: score = [8, twoCards[0], twoCards[1], 0, 0, 0];break;

        // if card counts are 2 or 3, its full house, put the 3 card as major, 2 card as minor
        case 2: score = [7, twoCards[1], twoCards[0], 0, 0, 0];break;
        case 3: score = [7, twoCards[0], twoCards[1], 0, 0, 0];break;
      }
    }

    // If 3 different card types - its a three of a kind or two pair
    if (cardLen == 3) {

      // If there is a card count of 3 present, its 3 of a kind
      if (Object.values(cards).includes(3)) {
        score[0] = 4;

        // Go through cards, if count is 3, set it as Major, and set others as minor in decending order
        let leftovers = [];
        for (let card3 in cards) {
          if (cards[card3] == 3) {
            score[1] = parseInt(card3);
          } else {
            leftovers.push(parseInt(card3));
          }
          score[2] = Math.max(...leftovers);
          score[3] = Math.min(...leftovers);
        }

      // If no 3 count, its 2 pair, assign pairs as major/minor based on value, and then extra card  
      } else {
        score[0] = 3;
        let majors = [];
        for (let card22 in cards) {
          if (cards[card22] == 2) {
            majors.push(parseInt(card22));
          } else {
            score[3] = parseInt(card22);
          }
          score[1] = Math.max(...majors);
          score[2] = Math.min(...majors);
        }
      }
    }

    // If 4 different card types - Its a single pair
    if (cardLen == 4) {
        score[0] = 2;
        let minors = [];

        // Check cards, the pair is the Major, all other cards minors in decending order
        for (let card2 in cards) {
          if (cards[card2] == 2) {
            score[1] = parseInt(card2);
          } else {
            minors.push(parseInt(card2));
          }
          minors.sort((a,b) => b-a);
          score[2] = minors[0];
          score[3] = minors[1];
          score[4] = minors[2];
        }
    }

    // Return the score array
    return score;
  }
}

const testArr = [
  '8C TS KC 9H 4S 7D 2S 5D 3S AC',
  '5C AD 5D AC 9C 7C 5H 8D TD KS',
  '3H 7H 6S KC JS QH TD JC 2D 8S',
  'TH 8H 5C QS TC 9H 4D JC KS JS',
  '7C 5H KC QH JD AS KH 4C AD 4S'
];

console.log(pokerHands(testArr));

Code Explanation
For this problem, there are two major design decisions that need to be addressed.

  1. How to determine what type of hand a player has (straight, flush, etc)
  2. How to compare two hands to determine which player wins

For this solution, the first issue was resolved by simply counting the cards and suits found in a hand, and putting them into an object with the card type as the keys, and the count as the value:

EX: { 7: 3, 13: 2 } - This indicates three 7’s, and two Kings => full house

Once you compile the counts, you can then categorize the hands by either the counts (if suit count values contains 5, its a flush, if card count values contains 4, its a 4 of a kind) or by checking the length of keys (if suit length is 1, its a flush, if card count length is 2, its a 4 of a kind or full house). This solution uses the length.

For the second issue on how to compare hands for a winner, this solution uses an array it calls score. The score’s first value is the “hand score” which is determines by the type of hand… a full house scores a 7, two pair scores a 3 etc. Then when comparing two scores the winner is whoever has the highest value. The remainder of the score array is used to store the values of the cards at play, so if the hand score is a tie, you then can check card values to determine the winner. The score array looks like this:

[ hand score, major card value, minor card value, extra card value, extra card value, extra card value]

In this case, major card value is the value of the card related to the hand score… for a three of a kind, its the card you have three of. The minor card is for hands that have two, like the full house, where first check the three cards value, then check the two cards value. The remainer are the additional cards in decending order. If no remainders they are just 0.

With that score array, now to determine who wins, all you’d have to do is check the first value, if it ties, check the second value, if it ties, third, and so on.

With this design layout, the function just then needs to go through each value in the array, split the hands string into two separate hands, calculate the score of the first, the score of the second, and then compare those two for a winner. If Player 1 wins, you increment a counter.

Challenge: Problem 54: Poker hands

Link to the challenge:

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.