C: More Efficient Way of Checking for Equivalence in Array? - c

I have the function working, but I am looking to see if there's a more efficient way of checking if there are three of a kind in my hand of cards so I don't need so many nested loops. I'm not sure if there even is though. I am using enumerations and structures for my card in the deck.

There are multiple ways you can do this. The best way depends on the type of entries you have in the array?
Are the total cards limited? What I mean is that is the maximum value that can be in the array bounded? (Since they are cards I guess they can go from 1-13).
Then the best option would be to make another array counter of size 13 and initialize it with 0. They iterate over all the elements and then increment the counter of the card you see. At any point if the counter == 3 return true else at the end false.
The implementation would be
int counter[13] = {0};
for ( i = 0; i < 5; i++ ){
card = hands[i].cardRank;
counter[card]++;
if (counter[card] == 3)
return true;
return false;
If the values of the card is not bounded, you can use a hashmap in a similar way.
If hashmap datastructure is not available you, you will have to use another approach.
Here you will first sort the array. So if there are 3 occurrences they will come together. And in a single loop you can check them. For every element check if the next and the next to next element is the same as it. If yes return true.
Else finally return false.
I think the code for that would be easy to implement.
I can post if you are not able to figure out.

You could make an integer array with one element for each card rank. This will count how many cards of that rank are in the hand. Iterate through the hand, and for each card, increment the rank-count array for the corresponding rank. Then iterate through the rank-count array and see if any values equal 3. This method would also work well for finding four of a kind. If you iterate through the rank-count array in descending order, you can find the highest rank group.

If your hand is sorted, you can do this :
for(int i = 0 ; i < 5 - 2; ++i){
if (hand[i].cardRank == hand[i+1].cardRank && hand[i].cardRank == hand[i+2].cardRank){
// triplets found
}

Related

How to check the elements of a row in a 2D Array

So, what I am trying to do is a three in a row game, and so far I have managed to make it work, but I am struggling a bit when it comes to getting a winner, since I need to check that all the elements of either a row, a column or a diagonal are the same.
So far I have managed to get it to kinda work by using a boolean, a counter and a for loop. Here is an example of how my code looks
//Code to check the rows horizontally
public void checkH(){
int cont1 = 0;
Boolean winner1 = false;
for(int i=0;i<size;i++){
if(a[0][i]==1 || a[1][i]==1 || a[2][i]==1){
cont1++;
if(cont1==3){
winner1 = true;
}
So, as y'all can see what I am doing in that code is telling the program that if the array in either one of the rows is equal to one and if that same case happens when it goes through all the positions in the row, then the counter is going to add plus one, and once the counter hits 3, the boolean will be true and there will be a winner, but here is the catch: if, for example, the 2D array looks like this:
int a[][] = {{1,0,0},
{1,1,0},
{0,0,0}};
then the counter is still hitting three, even though they are not aligned. I know I havent specified that kind of condition in the program, but that's what I am struggling with. What I would like to do is to be able to make that condition with loops, so that I dont have to fill the whole thing with if statements.
Any leads you guys could give me on this would be highly appreciated. Thanks in advance!
If you are finding it difficult to search for a solution/tutorial on the web, notice that the three in a row game is also called tic-tac-toe. So, if you search for "tic tac toe algorithm" you will find several examples on how to solve it, as it is a somewhat usual interview question. Here is a reference for the reader’s convenience.
Now, for the desire to use for loops instead of chained ifs (or an if with multiple logical comparisons), it is a question about row-wise, column-wise and diagonal-wise traversal of a matrix. Here is a reference for the row and column traversals, and here is another reference for the diagonal traversal.
Specific to your question, below is a pseudo-code showing the check for column and row using for and the cell values to have a small number of if statements. But please notice this is just an example, as there are many interesting ways to solve a tic-tac-toe game that you may want to take a look, from traversing trees to using a string and regex.
public bool checkRow() {
int i, j;
int count = 0;
// accessing element row wise
for (i = 0; i < MAX; i++) {
for (j = 0; j < MAX; j++) {
// Considering we were checking for 1
// And array can have 0 or 1
// You can add the cell value and avoid an if
count += arr[i][j];
// if you go with arr[j][i] you will be traversing the columns and not the rows.
}
// if all cells in the row are 1, we have a winner
if(count == MAX)
return true;
}
return false
}

Finding the amount of different elements at array

We have an array at size n. How we can find how many different types of elements we have at n and what is the amount of each one?
For example: at {1,-5,2,-5,2,7,-5,-5} we have 4 different types, and the array of the amounts will be: {1,2,1,4}.
So my questions are:
How we can find how many different elements there is at the array?
How we can count the amount if each one?
Now, I try to solve it at Omega(n), I try a lot but I didn't find a way. I try to solve it with hash-tables.
You are trying to get frequency of an element in an array.
Initialize a Hash where every new key is initialized with value 0.
Loop through array and add this key to hash and increment the value.
In JavaScript:
hash = {};
a = [1,-5,2,-5,2,7,-5,-5];
for(var i = 0; i < a.length; ++i) {
if(hash[a[i]] === undefined)
hash[a[i]] = 0
hash[a[i]] = hash[a[i]] + 1;
}
console.log(hash.toSource());
The syntax and specific data structures you use will vary between languages, but the basic idea would be to store a running count of the number of instances of each value in an associative data structure (HashMap, Dictionary, whatever your language calls it).
Here is an example that will work in Java (I took a guess at the language you were using).
It's probably bad Java, but it illustrates the idea.
int[] myArray = {1,-5,2,-5,2,7,-5,-5};
HashMap<Object,Integer> occurrences = new HashMap<Object,Integer>();
for (int i=0;i<myArray.length;i++)
{
if (occurrences.get(myArray[i]) == null)
{
occurrences.put(myArray[i],1);
}
else
{
occurrences.put(myArray[i],occurrences.get(myArray[i])+1);
}
}
You can then use your HashMap to look up the distinct elements of the array like this
occurrences.keySet()
Other languages have their own HashSet implementations (Dictionaries in .NET and Python, Hashes in Ruby).
There are different approaches to solve this problem.The question that asked here might be asked in different ways.Here the the simple way to do it with std::map which is available in STL libraries.But remember it will be always sort by key.
int arr[]={1,-5,2,-5,2,7,-5,-5};
int n=sizeof(arr)/sizeof(arr[0]);
map<int,int>v;
for(int i=0;i<n;i++)
{
if(v[arr[i]])
v[arr[i]]++;
else
v[arr[i]]=1;
}
map<int,int>::iterator it;
for(it=v.begin();it!=v.end();++it)
cout<<it->first<<" "<<it->second<<endl;
return 0;
it will show output like
-5 4
1 1
2 2
7 1
I suggest you read about 'Count Sort'
Although i am not sure i understood correctly what you actually want to ask. Anyway, i think you want to:
1.) Scan an array and come up with the frequency of each unique element in that array.
2.) Total amount of unique elements
3.) all that in linear computational time
I think, what you need is Counting Sort. See algo on wiki.
You can obviously skip the sorting part. But you must see how it does the sorting (the useful part for your problem). It, first, calculates a histogram (array of size nominally equal to the number of unique elements in you original array) of frequency of each key. This works for integers only (although you can always sort other types by putting integer pointers).
So, every index of this histogram array will correspond to an element in your original array, and the value at this index will correspond to the frequency of this element in the original array.
For Example;
your array x = {3, 4, 3, 3, 1, 0, 1, 3}
//after calculation, you will get
your histogram array h[0 to 4] = {1, 2, 0, 4, 1}
i hope that is what you asked

Limit input data to achieve a better Big O complexity

You are given an unsorted array of n integers, and you would like to find if there are any duplicates in the array (i.e. any integer appearing more than once).
Describe an algorithm (implemented with two nested loops) to do this.
The question that I am stuck at is:
How can you limit the input data to achieve a better Big O complexity? Describe an algorithm for handling this limited data to find if there are any duplicates. What is the Big O complexity?
Your help will be greatly appreciated. This is not related to my coursework, assignment or coursework and such. It's from the previous year exam paper and I am doing some self-study but seem to be stuck on this question. The only possible solution that i could come up with is:
If we limit the data, and use nested loops to perform operations to find if there are duplicates. The complexity would be O(n) simply because the amount of time the operations take to perform is proportional to the data size.
If my answer makes no sense, then please ignore it and if you could, then please suggest possible solutions/ working out to this answer.
If someone could help me solve this answer, I would be grateful as I have attempted countless possible solution, all of which seems to be not the correct one.
Edited part, again.. Another possible solution (if effective!):
We could implement a loop to sort the array so that it sorts the array (from lowest integer to highest integer), therefore the duplicates will be right next to each other making them easier and faster to be identified.
The big O complexity would still be O(n^2).
Since this is linear type, it would simply use the first loop and iterate n-1 times as we are getting the index in the array (in the first iteration it could be, for instance, 1) and store this in a variable names 'current'.
The loop will update the current variable by +1 each time through the iteration, within that loop, we now write another loop to compare the current number to the next number and if it equals to the next number, we can print using a printf statement else we move back to the outer loop to update the current variable by + 1 (next value in the array) and update the next variable to hold the value of the number after the value in current.
You can do linearly (O(n)) for any input if you use hash tables (which have constant look-up time).
However, this is not what you are being asked about.
By limiting the possible values in the array, you can achieve linear performance.
E.g., if your integers have range 1..L, you can allocate a bit array of length L, initialize it to 0, and iterate over your input array, checking and flipping the appropriate bit for each input.
A variance of Bucket Sort will do. This will give you complexity of O(n) where 'n' is the number of input elements.
But one restriction - max value. You should know the max value your integer array can take. Lets say it as m.
The idea is to create a bool array of size m (all initialized to false). Then iterate over your array. As you find an element, set bucket[m] to true. If it is already true then you've encountered a duplicate.
A java code,
// alternatively, you can iterate over the array to find the maxVal which again is O(n).
public boolean findDup(int [] arr, int maxVal)
{
// java by default assigns false to all the values.
boolean bucket[] = new boolean[maxVal];
for (int elem : arr)
{
if (bucket[elem])
{
return true; // a duplicate found
}
bucket[elem] = true;
}
return false;
}
But the constraint here is the space. You need O(maxVal) space.
nested loops get you O(N*M) or O(N*log(M)) for O(N) you can not use nested loops !!!
I would do it by use of histogram instead:
DWORD in[N]={ ... }; // input data ... values are from < 0 , M )
DWORD his[M]={ ... }; // histogram of in[]
int i,j;
// compute histogram O(N)
for (i=0;i<M;i++) his[i]=0; // this can be done also by memset ...
for (i=0;i<N;i++) his[in[i]]++; // if the range of values is not from 0 then shift it ...
// remove duplicates O(N)
for (i=0,j=0;i<N;i++)
{
his[in[i]]--; // count down duplicates
in[j]=in[i]; // copy item
if (his[in[i]]<=0) j++; // if not duplicate then do not delete it
}
// now j holds the new in[] array size
[Notes]
if value range is too big with sparse areas then you need to convert his[]
to dynamic list with two values per item
one is the value from in[] and the second is its occurrence count
but then you need nested loop -> O(N*M)
or with binary search -> O(N*log(M))

8085 Assembly Language program to create an array in ascending order from 2 other arrays

I have two arrays in ascending order that I need to combine to create a new array that is also in ascending order. One way I have though about doing this is putting one of the arrays into the new one, and then going through the second array and comparing every value in it to the ones in the new array and putting it in the right spot. This seems inefficient though.
I have also thought about comparing the first values of the array, and then comparing the one that doesn't get put in, to the next value of the other array.
What do you think of my ideas? Is there an easier way to do this?
I think simplest way to do this is having one index for each of the arrays:
while(index_result < array_result_length)
if (index1 < array1_length)
if (index2 < array2_length)
if (array1[index1] < array2[index2])
array_result[index_result] = array1[index1]
index1++
else
array_result[index_result] = array2[index2]
index2++
else
array_result[index_result] = array1[index1]
index1++
else
array_result[index_result] = array2[index2]
index2++
index_result++

what's efficient way to filter an array

I am programming c on linux and I have a big integer array, how to filter it, say, find values that fit some condition, e.g. value > 1789 && value < 2031. what's the efficient way to do this, do I need to sort this array first?
I've read the answers and thank you all, but I need to do such filtering operation many times on this big array, not only for once. so is iterating it one by one every time the best way?
If the only thing you want to do with the array is to get the values that match this criteria, it would be faster just to iterate over the array and check each value for the condition (O(n) vs. O(nlogn)). If however, you are going to perform multiple operations on this array, than it's better to sort it.
Sort the array first. Then on each query do 2 binary searches. I'm assuming queries will be like -
Find integers x such that a < x < b
First binary search would find the index i of the element such that Array[i-1] <= a < Array[i] and second binary search would find the index j such that Array[j] < b <= Array[j+1]. Then your desired range would be [i, j].
This algorithm's complexity is O(NlogN) in preprocessing and O(N) per query if you want to iterate over all the elements and O(logN) per query if you just want to count the number of filtered element.
Let me know if you need help implementing binary search in C. There is library function named binary_search() in C and lower_bound() and upper_bound() in C++ STL.
You could use a max heap implemented as an array of the same size as the source array. Initialize it with min-1 value and insert values into the max-heap as the numbers come in. The first check would be to see if the number to be inserted is greater than the first element, if it's not, discard it, if it is larger then insert it into the array. To get the list of numbers back, read all numbers in the new array till min-1.
To filter the array, you'll have to look at each element once. There's no need to look at any element more than once, so a simple linear search of the array for items matching your criteria is going to be as efficient as you can get.
Sorting the array would end up looking at some elements more than once, which is not necessary for your purpose.
If you can spare some more memory, then you can scan your array once, get the indices of matching values and store it in another array. This new array will be significantly shorter since it has only indices of values which match a specific pattern! Something like this
int original_array[SOME_SIZE];
int new_array[LESS_THAN_SOME__SIZE];
for ( int i=0,j=0; i<SOME_SIZE; i++)
{
if ( original_array[i]> LOWER_LIMIT && original_array[i]< HIGHER_LIMIT )
{
new_array[j++] = i;
}
}
You need to do the above once and form now on,
for ( int i=0; i< LESS_THAN_SOME_SIZE; i++ )
{
if ( original_array[new_array[i]]> LOWER_LIMIT && original_array[new_array[i]]< HIGHER_LIMIT )
{
printf("Success! Found Value %d\n", original_array[new_array[i]] )
}
}
So at the cost of some memory, you can save considerable amount of time. Even if you invest some time in sorting, you have to parse the sorted array every time. This method minimizes the array length as well as the sorting time ( at the cost of extra memory, of course :) )
Try this library: http://code.google.com/p/boolinq/
It is iterator-based and as fast as can be, there are no any overhead. But it needs C++11 standard. Yor code will be written in declarative-way:
int arr[] = {1,2,3,4,5,6,7,8,9};
auto items = boolinq::from(arr).where([](int a){return a>3 && a<6;});
while (!items.empty())
{
int item = items.front();
...
}
Faster than iterator-based scan can be only multithreaded scan...

Resources