-1

I am currently working on a little mini program that will determine if a vector of 5 strings contains a full house. A full house in my program has a pair of cards and 3 of a kind.

For example: ["A", "A", "A", "K", "K"] would be a full house, while ["10", "J", "10", "10", "10"] would not be one.

I have written my main function such that a user can read the card values into a vector with this code below:

int main()
{
    vector<string> hand;
    string input;

    for (int i = 0; i < 5; i++)
    {
        cout << "Card " << i + 1 << ": ";
        cin >> input;

        hand.push_back(input);
    }
}

I would like to write a bool function that takes the vector as a parameter and returns true if the vector contains a full house, and false if it does not. My problem is that I am not sure of an efficient way of looping through the vector in the function and finding the frequency of each string to determine if the vector has a full house.

For example, I would like my function to be somewhat like the one below:

bool isFullHouse(vector<string> hand)
{
     // loop through vector
     // record instance of string in vector
     // determine if the string has appeared either 2 times or 3 times in the vector

     // if it contains a full house
     return true

     // else
     return false
}

Does anyone have a decent way of achieving this task?

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Note: It's a common convention in card code to use `T` for 10 so that all cards are one character, which when paired with a suit is like `2S` or `TC`, very predictable and easy to work with. – tadman Nov 18 '20 at 23:27
  • Tip: Sort the array. If the first two and last three, or the first three and last two match, full house detected. – tadman Nov 18 '20 at 23:28
  • I'd sort as mentioned above, but you could also use a `map` to count the cards and then check for the right combination. – Retired Ninja Nov 18 '20 at 23:32
  • I support the idea of using `std::map`, where `std::string` is the card value (as string) or the "hand" and the `int` is the number of occurrences. – Thomas Matthews Nov 18 '20 at 23:39
  • On that theme, for a limited number of hands, the hands themselves could be hashed to quickly determine if there is a full house. `std::unordered_map full_houses;` sort of. – Ted Lyngmo Nov 18 '20 at 23:51

2 Answers2

1

You can use standard algorithms to write the function like this:

bool isFullHouse(vector<string> hand)
{
   // put all cards matching the first one at the beginning
   auto p = std::partition(hand.begin(), hand.end(), 
                           [first_card = hand[0]] (auto card) {
                             return first_card == card;
                           });
   
   // count cards matching the first one
   auto num = std::distance(hand.begin(), p);

  return (p == 2 or p == 3)                             // 2 or 3 cards 
      && std::equal(hand.begin() + 1, p, hand.begin())  // same card at the beginning
      && std::equal(p + 1, hand.end(), p);              // same card at the end
}

Efficiency is not a major concern here since you are dealing with a vector of 5 short strings, but this is an O(n) algorithm. Not that the n is relevant since you only have 5 cards, but all the algorithms used here are O(n).

cigien
  • 57,834
  • 11
  • 73
  • 112
0

You can also make your life simple and count the cards . . .

#include <iostream>
#include <unordered_map>
#include <string>

int main() {

    // Define container
    std::unordered_map<std::string, unsigned int> hand{};

    // Read all values and count them
    int i{};
    for (std::string card{}; (i < 5) and (std::cin >> card); hand[card]++, ++i);

    // Show result
    std::cout << (((hand.size() == 2) and ((hand.begin()->second == 2) or (hand.begin()->second == 3))) ? "Full House" : "");
}
A M
  • 14,694
  • 5
  • 19
  • 44