Tommaso Masaracchio
Tommaso Masaracchio

Reputation: 21

Function to count unique values in array of int

I have a list of numbers and I want to increase by a unit the value of tot only if the element of the list is different from every element before it.

Basically I'm counting how many element the list has, if we don't consider the duplicates.

My code increases the count every time the function is different from at least 1 element.

How can i fix it?

My code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    int i;
    int j = 0;
    int tot = 0;
    int n = 11;
    int list[12] = {0, 8, 2, 12, 6, 0, 4, 8, 3, 2, 3, 0};
    puts("[MEMBERS COMPARED AND INDEXES]");
    for (i = 1; i < n; i++)
    {
        for (j = i - 1; j > 0; j--)
        {
            printf("\n %d %d %d %d\n", list[i], list[j], i, j);

            //printf("\n %d %d \n", i,j);
            if (list[i] != list[j])
                tot++;
        }
    }
    puts("[TOT]");
    printf("\n %d", tot);
}

The code with this sample array should produce a total of 7, but it's 42.

Complete output:

[MEMBERS COMPARED AND INDEXES]

2 8 2 1

12 2 3 2

12 8 3 1

6 12 4 3

6 2 4 2

6 8 4 1

0 6 5 4

0 12 5 3

0 2 5 2

0 8 5 1

4 0 6 5

4 6 6 4

4 12 6 3

4 2 6 2

4 8 6 1

8 4 7 6

8 0 7 5

8 6 7 4

8 12 7 3

8 2 7 2

8 8 7 1

3 8 8 7

3 4 8 6

3 0 8 5

3 6 8 4

3 12 8 3

3 2 8 2

3 8 8 1

2 3 9 8

2 8 9 7

2 4 9 6

2 0 9 5

2 6 9 4

2 12 9 3

2 2 9 2

2 8 9 1

3 2 10 9

3 3 10 8

3 8 10 7

3 4 10 6

3 0 10 5

3 6 10 4

3 12 10 3

3 2 10 2

3 8 10 1

[TOT]

42

Upvotes: 1

Views: 929

Answers (3)

anotherOne
anotherOne

Reputation: 1573

The loops should start from 0 and n should be 12 (or you should do i<=n)

It would be better to define n as a constant

#dedine N 12

And then declare

int list[N] = {...

Or, as stated in the comments, you can compute the length of the array automatically

#define N (sizeof(list) / sizeof(list[0]))

You can now use N instead of your n without needing to specify the length of the list array

int list[] = { 0, 8, etc... };

Anyway, you can solve the issue with a flag variable telling whether the current element is different from all the previous.

#include <stdio.h>
#include <stdlib.h>
#include<string.h>

#define N (sizeof(list) / sizeof(list[0]))

int main()
{
    int i, j, flag;
    int tot = 0;
    int list[] = {0, 8, 2, 12, 6, 0,4, 8, 3, 2, 3, 0};
    
    for (i = 0; i < N; i++) {
    
        flag = 1;
        
        for (j = 0; j < i; j++) {
                    
            if (list[i] == list[j]) {
                flag = 0;
                break;
            }
        }

        if( flag ) tot++;
    }
    
    puts("[TOT]");
    printf("\n %d", tot);
}

Upvotes: 0

Edward Savage
Edward Savage

Reputation: 309

You need two arrays, current and target of the same size to represent the raw data and unique entities respectively. You also need a total unique variable, or you can simply write the return out in a print at the end of the function.

Unique entity function

Taking each element of current and comparing it to all elements in target will enable target to contain all unique entities. Simply finding the target size will give you the total number of unique entities found.

Alternatively, The complexity of your current attempt is O(N^2) already. Applying a sorting algorithm to work within that complexity and checking through the result for non-consecutive values will yield you the desired unique entities after being sorted. Adding a counter to that will provide you with a valid solution.

Resources/Reading

If you'd like a deeper understanding (with code examples) this explains in detail the steps you need to take.

Upvotes: 0

anastaciu
anastaciu

Reputation: 23822

You're on the right track, going back in the array to see if the current value already exists, if not, count it as unique, otherwise move on.

The problem is that you are counting every different value before, regardless if it was alread counted, or if it is unique, this, of course, will give you a much larger total, you need to count unique values only once, something like this:

Live demo

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

int main()
{
    int tot = 0;
    bool exists;
    int list[] = {0, 8, 2, 12, 6, 0, 4, 8, 3, 2, 3, 0}; // size can be omited

    for (size_t i = 0; i < sizeof list / sizeof list[0]; i++)
    {
        exists = false; //flag to track repeated values

        //loop back to check if it is already in the array
        for (int j = i - 1; j >= 0; j--)
        {
            if (list[i] == list[j])
            {
                exists = true;
                break;
            }
        }
        if (!exists) // count if it is not already in the array
        {
            tot++;
        }
    }
    printf("Total unique values: %d", tot);
    return EXIT_SUCCESS;
}

Another solution would be to sort the array, you can use qsort or make your own sorting algorithm, this makes things easier because the repeated values are stored contiguosly.

It's hard to tell if it would be better, adding the sorting overhead and then check for duplicates might even be less efficient than this solution which is already O(N2), this will depend on the quality of the sorting algorithm.

Upvotes: 1

Related Questions