1

I am making a program to identify whether a 5 card ( user input ) array is a certain hand value. Pair, two pair, three of a kind, straight, full house, four of a kind ( all card values are ranked 2-9, no face cards, no suit ). I am trying to do this without sorting the array. I am currently using this to look through the array and identify if two elements are equal to each other

bool pair(const int array[])
{
 for (int i = 0; i < array; i++)
 {
 if (array[i]==aray[i+1])
 {
    return true;
 }
 else 
    return false;
}

Does this section of code only evaluate whether the first two elements are the same, or will it return true if any two elements are the same? I.E if the hand entered were 2,3,2,4,5 would this return false, where 2,2,3,4,5 would return true? If so, how do I see if any two elements are equal, regardless of order, without sorting the array?

edit: please forgive the typos, I'm leaving the original post intact, so as not to create confusion.

I was not trying to compile the code, for the record.

  • 4
    *... will it return true if any two elements are the same?* Why don't you try it out? – DeiDei Sep 08 '16 at 20:08
  • 1
    No this will only check if two *consecutive* elements are the same, so this would require the array be sorted to work. – Cory Kramer Sep 08 '16 at 20:08
  • Apart from the typos, this will *not* work. It will only compare two adjacent items - and if you did not sort, it won't work. You'll also run out of the array. Make it two nested loops to fix. – Jongware Sep 08 '16 at 20:09
  • 1
    Why are you trying to do this unsorted? Sorting the data set makes your life a lot easier. – NathanOliver Sep 08 '16 at 20:10
  • @NathanOliver: while definitely true for a larger data set, surely two nested loops will outperform a combined sort-then-test for just 5 items? – Jongware Sep 08 '16 at 20:15
  • @RadLexus For the patterns mentioned, sorted data should be easier to deal with. – ToniBig Sep 08 '16 at 20:18
  • 1
    @RadLexus I wasn't really looking at it in a performance standpoint but from an ease of logic point of view. If this performance critical then profiling would need to be done. If not then I would pick the easier, slightly less performant way. – NathanOliver Sep 08 '16 at 20:19

4 Answers4

1

It will do neither:

  1. i < array will not work, array is an array not an int. You need something like int arraySize as a second argument to the function.
  2. Even if you fix that then this; array[i]==aray[i+1] will cause undefined behaviour because you will access 1 past the end of the array. Use the for loop condition i < arraySize - 1.
  3. If you fix both of those things then what you are checking is if 2 consecutive cards are equal which will only work if the array is sorted.

If you really cant sort the array (which would be so easy with std::sort) then you can do this:

const int NumCards = 9; // If this is a constant, this definition should occur somewhere. 

bool hasPair(const int array[], const int arraySize) {

    int possibleCards[NumCards] = {0}; // Initialize an array to represent the cards. Set 
                                       // the array elements to 0.

    // Iterate over all of the cards in your hand.
    for (int i = 0; i < arraySize; i++) {

       int myCurrentCard = array[i]; // Get the current card number.
       // Increment it in the array.
       possibleCards[myCurrentCard] = possibleCards[myCurrentCard] + 1; 


       // Or the equivalent to the above in a single line. 

       possibleCards[array[i]]++; // Increment the card so that you 
                                  // count how many of each card is in your hand.
    }

    for (int i = 0; i < NumCards; ++i) {
        // If you want to check for a pair or above.
        if (possibleCards[i] >= 2) { return true; }
        // If you want to check for exactly a pair.
        if (possibleCards[i] == 2) { return true; }
    }
    return false;
}

This algorithm is actually called the Bucket Sort and is really still sorting the array, its just not doing it in place.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
  • Thank you for your response. It was very helpful. Is it necessary to create the possibleCards array to store the counted cards? Could this not be done by simply declaring a counter and increment it? Also, why do you use "++i" in the second for statement? – Bob Newhart Sep 08 '16 at 21:08
  • @BobNewhart Well you would need 9 counters, 1 for each card, using an array is much easier (and scalable). `++i` and `i++` are equivalent in this case, but you should prefer prefix increment because in other cases it may be faster. – Fantastic Mr Fox Sep 08 '16 at 21:16
  • Supposing I am passing a constant array as an argument, is it possible to still sort the array, or does a constant array indicate constant elements. That is, array[0] will always be its initial value? I am under the impression that passing an array as constant serves the purposes of not altering the original array? – Bob Newhart Sep 08 '16 at 21:26
  • @BobNewhart You can always sort it into a new, temporary array. or simply iterate on them and add them to a sorted datatype like `std::set`. – Fantastic Mr Fox Sep 08 '16 at 21:32
  • So, I used your strategy for counting based on card values, which works splendidly for pair, three of a kind, four of a kind. For full house I used: if(containsPair(hand) && containsThreeOfaKind(hand) using this strategy as well. How could I utilize to evaluate for two pair, or a straight ( without sorting )? – Bob Newhart Sep 09 '16 at 04:03
  • 1
    @bobnewhart I am not going to do your homework for you. You will need to figure it out, if you have troubles ask another question. – Fantastic Mr Fox Sep 09 '16 at 04:07
  • Would you mind explaining how your code `const int NumCards = 9 int possibleCards[NumCards] = {0}; for (int i = 0; i < arraySize; i++) { possibleCards[array[i]]++;` -------------------------------------------------identifies the equal elements in the array? – Bob Newhart Sep 09 '16 at 07:23
  • @BobNewhart I added more detailed comments. But from here on in i think it would help yopu to get a good quality c++ textbook: http://stackoverflow.com/a/388282/1294207 – Fantastic Mr Fox Sep 09 '16 at 15:05
0
for (int i = 0; i < array; i++)
 {
 if (array[i]==aray[i+1])
 {
    return true;
 }
 else 
    return false;

This loop will only compare two adjacent values so the loop will return false for array[] = {2,3,2,4,5}.

You need a nested for loop:

#include <stdio.h>
#include <stdbool.h>
int main()
{
  int unsortedArray[] = {2,3,2,4,5};
  int size = 5;

  for(int i=0;i<size-1;i++)
  {  for(int j=i+1;j<size;j++)
      {   if(unsortedArray[i]==unsortedArray[j])
           {  printf("matching cards found\n");
              return 0;
            }
       }
    }   
    printf("matching cards not found\n");
    return 0;
}

----EDIT------

Like Ben said, I should mention the function above will only find the first instance of 2 matching cards but it can't count how many cards match or if there are different cards matching. You could do something like below to count all the number of matching cards in the unsortedArray and save those values into a separate array. It's messier than the implementation above:

 #include <iostream>
 #include <stdio.h>
 #include <stdbool.h>

 #defin NUM_CARDS 52;

 using namespace std;

    int main()
    {
      int T;
      cin>>T;
      while(T--)
      {
      int N,i,j;
      cin>>N;
      int unsortedArray[N];
      for(int i=0;i<N;i++)
        cin>>unsortedArray[i];

      int count[NUM_CARDS]={0};
      int cnt = 0;

      for( i=0;i<N-1;i++)
      {     
        for( j=i+1;j<N;j++)
        {  if(unsortedArray[i]==-1)
              break;      
           if(unsortedArray[i]==unsortedArray[j])
           { 
              unsortedArray[j]=-1;
              cnt++;
           }
        }
           if(unsortedArray[i]!=-1)
           {  
              count[unsortedArray[i]]=cnt; //in case you need to store the number of each cards to
                                           // determine the poker hand.
              if(cnt==1)
               cout<<" 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
              else if(cnt>=2)
               cout<<" more than 2 matching cards of "<<unsortedArray[i]<<" was found"<<endl;
              else
                cout<<" no matching cards of "<<unsortedArray[i]<<" was found"<<endl;

            cnt = 0;
            }
        }
JJTO
  • 847
  • 2
  • 8
  • 13
  • Probably not important but this will check for any 2 matching cards, if you have a three of a kind it will still return true. This may be desired, i don't know. But maybe mention that. – Fantastic Mr Fox Sep 08 '16 at 20:22
0

do you know the meaning of return keyword? return means reaching the end of function, so in your code if two adjacent values are equal it immediately exits the function; if you want to continue checking for other equality possibilities then don't use return but you can store indexes of equal values in an array

    #include <iostream>
    using namespace std;


    int* CheckForPairs(int[], int, int&);

    int main()
    {

        int array[ ]= {2, 5, 5, 7, 7};

        int nPairsFound = 0;

        int* ptrPairs = CheckForPairs(array, 5, nPairsFound);


        for(int i(0); i < nPairsFound; i++)
        {
                cout << ptrPairs[i] << endl;

        }

        if(ptrPairs)
        {
           delete[] ptrPairs;
           ptrPairs = NULL;
         }

        return 0;
    }

    int* CheckForPairs(int array[] , int size, int& nPairsFound)
    {

        int *temp = NULL;
        nPairsFound = 0;
        int j = 0;

        for(int i(0); i < size; i++)
        {
            if(array[i] == array[i + 1])
                nPairsFound++;
        }

        temp = new int[nPairsFound];

        for(int i(0); i < size; i++)
            {
                if(array[i] == array[i + 1])
                {
                    temp[j] = i;
                    j++;
                }
            }

        return temp;
    }
Raindrop7
  • 3,889
  • 3
  • 16
  • 27
  • Alternatively, I'm using this, http://pastebin.com/G536evw3 Which is always returning true, I believe. where am I going wrong here? – Bob Newhart Sep 09 '16 at 19:12
0

You could use a std::unordered_set for a O(n) solution:

#include <unordered_set>

using namespace std;

bool hasMatchingElements(const int array[], int arraySize) {
  unordered_set<int> seen;
  for (int i = 0; i < arraySize; i++) {
    int t = array[i];
    if (seen.count(t)) {
      return true;
    } else {
      seen.insert(t);
    }
  }
  return false;
}