So lets say i have an array of ints (max being its maximum size)
array = { 1, 7, 22, 3, 7, ... }
and i need to find a way to count the duplicates of each element in the previous array into another array like this one
duplicates = { { 1, 2 times }, { 7, 3 times } ...}
i know the syntax is wrong i just wanted to exemplify my goal (hope i expressed myself well enough) .. i have been thinking and i cant think of a way to do this (maybe it's simple but im kinda new at this) so i decided to post here for some guidance.
Thanks in advance
You could sort the array, maybe with an algorithm like qsort and then with a for or a while loop you can count how many times each element appear into the array since the duplicates will be one after another.
If you're under mac/linux type in the terminal man 3 qsort to see how it should be used.
If memory wasting does not cause any trouble in your case:
Define a struct
struct DuplicationInfo{
int number;
int times;
}
Then you can do a loop as follow
DuplicationInfo[max] duplicates;
// Initialze the array
for(int i=0; i < max; i++)
{
duplicates[i].times= 0;
duplicates[i].number = -1; // Any invalid number which you know is not in your array
}
for(int i = 0; i < max; i++){
// Look if the number is still in our duplicates list
for(int j=0; j<max;j++){
if(duplicates[j].number == array[i])
{
duplicates[j].times++;
break;
}
else if(duplicates[j].number == -1)
{
duplicates[j].times= 1;
duplicates[j].number = array[i];
break;
}
}
}
You could either sort the array in order to have the duplicates of a number just after the number and count them with a wile or you could use a structure with a number and frequency field. Each time you have to insert a new number into the array, if it is already into the array you just increase by one the frequency field.
Related
I want to create a function that can return the number distinct values present in a given array. If for eg the array is
array[5] = { 1 3 4 1 3}, the return value should be 3(3 unique numbers in array).
I've so far only got this:
int NewFucntion(int values[], int numValues){
for (i=0; i<numValues; i++){
Im a new coder/New to C language and im stuck on how to proceed. Any guidance would be much appreciated. Thanks
Add elements from the array to the std::set<T> and since the set is not allowing duplicate elements, you can then only get the number of elements from the set which gives you the number of distinct elements.
For example:
#include<set>
int NewFucntion(int values[], int numValues){
std::set<int> set;
for(int i=0; i<numValues; i++){
set.insert(values[i]);
}
return set.size();
}
int distinct(int arr[], int arr_size){
int count = arr_size;
int current;
int i, j;
for (i = 0; i < arr_size; i++){
current = arr[i];
for (j = i+1; j < arr_size; j++) // checks values after [i]th element.
if (current == arr[j])
--count; // decrease count by 1;
}
if (count >= 0)
return count;
else return 0;
}
Here's the explanation.
The array with its size is passed as an argument.
current stores the element to compare others with.
count is the number that we need finally.
count is assigned the value of size of the array (i.e we assume that all elements are unique).
(It can also be the other way round)
A for loop starts, and the first (0th) element is compared with the elements after it.
If the element reoccurs, i.e. if (current==arr[j]), then the value of count is decremented by 1 (since we expected all elements to be unique, and because it is not unique, the number of unique values is now one less than what it was initially. Hence --count).
The loops go on, and the value is decremented to whatever the number of unique elements is.
In case our array is {1,1,1,1}, then the code will print 0 instead of a negative value.
Hope that helps.
Happy coding. :)
I like wdc's answer, but I am going to give an alternative using only arrays and ints as you seam to be coding in c and wdc's answer is a c++ answer:
To do this thing, what you need to do is to go through your array as you did, and store the new numbers you go over in a different array lets call it repArray where there wont be any repetition; So every time you add something to this array you should check if the number isn't already there.
You need to create it and give it a size so why not numValues as it cannot get any longer than that. And an integers specifying how many of it's indexes are valid, in other words how many you have written to let's say validIndexes. So every time you add a NEW element to repArray you need to increment validIndexes.
In the end validIndexes will be your result.
I am doing a program in C which needs to take in a set of values (integers) into a 2D array, and then performs certain mathematical operations on it. I have decided to implement a check in the program as the user is inputting the values to avoid them from entering values that are already present in the array.
I am however unsure of how to go about this check. I figured out I might need some sort of recursive function to check all the elements previous to the one that's being entered, but I don't know how to implement it.
Please find below a snippet of my code for illustrative purposes:
Row and col are values inputted by the user for the dimension of the array
for (int i=0; i<row;i++){
for (int j=0; j<col; j++){
scanf("%d", &arr[i][j]); //take in elements
}
}
for (int i = 0; i < row; i++)
{
for (int j = 0; i < col; j++)
{
if (arr[i][j] == arr[i][j-1]){
printf("Duplicate.\n");}
else {}
}
}
I know this is probably not correct but it's my attempt.
Any help would be much appreciated.
I would suggest that your store every element you read in a temporary 1D array. Everytime you scan a new element, traverse the 1D array checking if the value exists or not. Although this is not optimal, this will be at least less expensive than traversing the 2D array everytime.
Example:
int temp[SIZE];
int k,elements = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
scanf("%d", &arr[i][j]); //take in elements
temp[elements] = arr[i][j];
elements++;
for (int k = 0; k < elements; k++) {
if (temp[k] == arr[i][j])
printf("Duplicate.\n"); //or do whatever you wish
}
}
}
A balanced tree inserts and searches in O(log N) time.
Since the algorithms are quite simple & standard and were published in the seminal books by Knuth, there are plenty of implementations out there, including a clear and concise one at codereview.SE (which is thus automatically CC-BY-SA 3.0; do apply a bugfix in the answer). Using it (as well as virtually any other one) is simple: start with node* root = NULL;, then insert and search, and finally free_tree.
Asymptotically, the best method is a hash table with O(1) for both, but that is probably an overkill (the algorithms are much more complex and memory footprint is larger) unless you have a lot of numbers. For C++, there's a standard implementation, yet there are plenty 3rd-party ones for C, too.
If your number of input values is small, even the tree may be an overkill, and simply looking through previous values would be fast enough. If your 2D array is contiguous in memory, you can access it as 1D with int* arr1d = (int*)&arr2d.
So i have this piece of code:
int* get_lotto_draw() //Returns an array of six random lottery numbers 1-49
{
int min = 1;
int max = 49;
int counter = 0;
srand(time(NULL));
int *arrayPointer = malloc(6 * sizeof(int));
for(counter = 0; counter <= 5; counter++)
{
arrayPointer[counter] = rand()%(max-min)+min;
}
return arrayPointer;
}
This gives me 6 int* but sometimes these int* values can be the same. How can i compare each of them to eachother, so that if they are the same number, it will re-calculate on of the values that are equal ? Thanks for your time.
make a search in the array for same number before storing the number as,
for(counter = 0; counter <= 5; counter++)
{
int x1 = 1;
while(x1)
{
int temp = rand()%(max-min)+min;
for(i = 0; i < counter; i++)
{
if(arrayPointer[i] == temp)
{
break;
}
}
if(i == counter)
{
x1 = 0;
arrayPointer[counter] = temp;
}
}
}
The problem is that random-number generators don't know or care about history (at least, not in the sense that you do--software random number generators use recent results to generate future results). So, your choices are generally to...
Live with the possibility of duplicates. Obviously, that doesn't help you.
Review previous results and discard duplicates by repeating the draw until the value is unique. This has the potential to never end, if your random numbers get stuck in a cycle.
Enumerate the possible values, shuffle them, and pick the values off the list as needed. Obviously, that's not sensible if you have an enormous set of possible values.
In your case, I'd pick the third.
Create an array (int[]) big enough to hold one of every possible value (1-49).
Use a for loop to initialize each array value.
Use another for loop to swap each entry with a random index. If you swap a position with itself, that's fine.
Use the first few (6) elements of the array.
You can combine the second and third steps, if you want, but splitting them seems more readable and less prone to error to me.
I have a big 2-D array, array[length][2]. the length= 500000.
In array[i][0]= hex number, array[i][1]= 0 or 1, which represents some information related to each hex number. Like this:
array[i][0] array[i][1]
e05f56f8 1
e045ac44 1
e05f57fc 1
e05f57b4 1
e05ff8dc 0
e05ff8ec 0
e05ff900 1
I want to get a new array which stores: the hex number,# of occurance, the sum of array[i][1] of the same hex number.
I write the code like this:
//First Sort the array according to array[][0]
int x,y,temp1,temp2;
for (x=lines_num1-2;x>=0;x--)
{
for (y=0;y<=x;y++)
{
if(array[y][0]>array[y+1][0])
{
temp1=array[y][0];
array[y][0]=array[y+1][0];
array[y+1][0]=temp1;
temp2=array[y][1];
array[y][1]=array[y+1][1];
array[y+1][1]=temp2;
}
}
}
// generate the new_array[][]
int new_array[length][3];
int n=0;
for (n=0; n<length; n++){
new_array[n][0]=0;
new_array[n][1]=0;
new_array[n][2]=0;
}
int prev = array[0][0];
new_array[0][0]=array[0][0];
new_array[0][1]=1;
new_array[0][2]=array[0][2];
for (k=1;k<length;k++)
{
if (array[k][0] == prev)
{
new_array[n][1]=new_array[n][1]+1;
new_array[n][2]=new_array[n][2]+array[k][0];
}else{
prev = array[k][0];
new_array[n+1][0]=array[k][0];
new_array[n+1][1]=new_array[n+1][1]+1;
new_array[n+1][2]=new_array[n+1][2]+array[k][0];
n++;
}
}
But the code seems not work as I expected. First the sorting is so slow. And It seems cannot generate the correct new_array. Any suggestion on how to deal with this.
Personally, I would write a hash function to index the result array with the hexadecimal value directly. Then it is simple:
struct {
unsigned int nocc;
unsigned int nsum;
} result[/* ... */];
/* calculate the results */
for (i = 0; i < LENGTH; ++i) {
int *curr = &array[i];
unsigned int index = hash(curr[0]);
result[index].nocc++;
result[index].nsum += curr[1];
}
If you want to sort your array, don't reinventing the wheel: use qsort from the standard C library.
Sorting is slow because you're using bubble sort to sort the data. Bubble sort has quadratic average complexity, which means it has to perform more then 100 billion comparisons and swaps to sort your array. For this reason, never use bubble sort. Instead, learn to use the qsort library function and apply it to your problem.
Also, your sorting code has at least one bug: when exchanging values for the second column of the array, you are getting the value with the wrong column index, [3] instead of [1].
For your scenario insertion sort is the right solution, while doing the insertion itself you could make the #count and the sum. When the sort is finished, you will have your result array as well.
The code might look something like this
int hex = 0, count = 0, sum = 0, iHole;
for (i=1; i < lines_num1 -1; i++)
{
hex = array[i][0];
count = array[i][1];
sum = array[i][2];
iHole = i
// keep moving the hole to next smaller index until A[iHole - 1] is <= item
while (iHole > 0 and array[iHole - 1][0] > hex)
{
// move hole to next smaller index
A[iHole][0] = A[iHole - 1][0];
A[iHole][1] = A[iHole - 1][1];
A[iHole][2] = A[iHole - 1][2];
iHole = iHole - 1
}
// put item in the hole
if (array[iHole][0] == hex)
{
array[iHole][1]++;
array[iHole][2] += array[iHole][0];
}
else
{
array[iHole][0] = hex;
array[iHole][1] = 1;
array[iHole][2] = hex;
}
}
So the cost of making the second array is cost of the sorting itself. O(n) best case, O(n^2) worst case, and you don't have to travel again to make the sum and count.
Remember this sort is a inplace sort. If you don't want to affect your original array that could be done as well with iHole pointing to the new array. The iHole should point to the tail of new array instead of "i"
i'm a beginner in c, i have attempted to insert a value into an array as i scan another array for a value higher than a threshold, if a value is over the set threshold in the array being searched then insert a number into the other array...
for (i = 0; i<lines[i][1]; i++) {
if (lines[i][1] > 6500) {
array[];
}
so what i mean is, if there is a value in lines[i][1] higher than 6500, then insert number "1" into array[].
However, with previous attempts it just overwrites the array rather than stacks on top of previous values.. i have another for loop attempting to do the same thing while searching another array.
for (i = 0; i<lines[i][0]; i++) {
if (lines[i][0] > 6500) {
array[];
}
The ideal output would be something like: 1 for values higher than in lines[i][0] and 2 for values higher than in lines[i][1], "array[] = {1,1,1,2,2,2,2,1,1,1,};"
and the values are inserted into the array as arrays are being scanned.
Please help... thank you
Just start a counter to keep track of the position where you last inserted the item on the destination array. For example:
int destPosition=0;
for (i = 0; i<lines[i][0]; i++) {
if (lines[i][0] > 6500) {
array[destPosition]=1;
destPosition++;
}
}