Facing Runtime error while Solving finding and counting duplicates in c - arrays

Can someone please help me i am facing runtime error while solving this problem.
I have first defined the integers and then used scanf to take the input.
Then i check whether the 2 consecutive elements of array are equal are not.
if they are equal i equate j variable to i+1 and so that it can traverse and find if same duplicate elements are side by side (eg- 15 15 15).
I increment the j element till a[j] is equal to a[i].
Then using i try to print the number with the number of occurences of it which is j-i and then assign i with vakue of j-1.
#include <stdio.h>
int main()
{
int n,j=0,i;
scanf("%d",&n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d",&a[i]);
}
for (i = 0; i < n - 1; ++i)
{
if(a[i]==a[i+1])
{
j=i+1;
while(j<n && a[i]==a[j])
{
j++;
}
printf("%d is appearing %d times\n",a[i],j-i);
}
i=j-1;
}
return 0;
}

The input array needs to be sorted first to count duplicated, the loop logic needs to be fixed to reassign the index i.
A fixed code might like this:
#include <stdio.h>
#include <stdlib.h>
static int cmp_intp(const void *p1, const void *p2) {
return *(const int *)p1 > *(const int *)p2;
}
int main() {
int n, j = 0, i;
scanf("%d", &n);
int a[n];
for (i = 0; i < n; ++i) {
scanf("%d", &a[i]);
}
qsort(a, n, sizeof(a[0]), cmp_intp);
for (i = 0; i < n;) {
if (i < n - 1 && a[i] == a[i + 1]) {
j = i + 1;
while (j < n && a[i] == a[j]) {
j++;
}
printf("%d is appearing %d times\n", a[i], j - i);
i = j;
} else {
++i;
}
}
return 0;
}

The problem is created by the line,
i=j-1;
in the case when two consecutive elements are not equal.
move it within the if condition.

Related

Program to find prime numbers from the set of numbers of Fibonacci series in C

I want to find prime numbers from the Fibonacci series after printing them. First, I implemented the code for Fibonacci then added each element into an array. Then passed the array to a method to check for prime. Wanted to try it with an array. Displaying the series but not the prime numbers from the following code.
#include <stdio.h>
int fib()
{
int a=0,b=1, arr[20];
arr[0] = a;
arr[1] = b;
printf("%d, %d,",a, b );
int c=0;
for(int i=2; i<=20; i++)
{
c=a+b;
arr[i] = c;
printf("%d,",c);
a=b;
b=c;
}
checkPrime(arr);
}
void checkPrime(int a[])
{
int i, count;
for(i=0; i<sizeof(a); i++)
{
count=0;
for(int j=2; j<=a[i]/2 ; j++)
{
if(a[i]%2==0)
count++;
}
if(count>1)
printf("%d is a Prime", a[i]);
}
}
int main()
{
fib();
}
Output of the code
0, 1,1,2,3,5,8,13,21,34,55,89,144,233,377,610,987,1597,2584,4181,6765,
8 is a Prime
You have certain bugs in your implementation.
In fib function you iterate until i <= 20 but your arr have length 20 therefore your loop will go out of bounds of array. You should iterate until i < 20 or increase length of your array.
In checkPrime function you iterate until i < sizeof(a). But sizeof function doesn't return size of your array. It returns size of type of variable that you pass to it therefore it will return sizeof(int*) which = 8 (in case you 64 bit machine but I guess you have). To fix this bug you should pass length of your array in checkPrime function and use it.
You don't reset the count variable after j loop.
checkPrime function doesn't check if the number is prime. You have wrong expression in your nested loop. To check if number N is prime you should check if there any divisor of N that at least less than sqrt(N). Your expression is wrong.
Considering the adjustments above I suggest the next solution:
void checkPrime(int a[], size_t a_len) {
int i, count;
for (i = 1; i < a_len; i++) {
count = 0;
for (int j = 2; j <= sqrt((double)a[i]); j++) {
if (a[i] % j == 0) {
count++;
break;
}
}
if (count == 0) {
printf("%d is a Prime\n", a[i]);
} else {
count = 0;
}
}
}
int fib() {
size_t arr_size = 21;
int a = 0, b = 1, arr[arr_size];
arr[0] = a;
arr[1] = b;
printf("%d, %d, ", a, b);
int c = 0;
for (int i = 2; i < arr_size; i++) {
c = a + b;
arr[i] = c;
if (i == arr_size - 1)
printf("%d ", c);
else
printf("%d, ", c);
a = b;
b = c;
}
printf("\n");
checkPrime(arr, arr_size);
}

I want to print the number of times an element is repeated in an array of random numbers in C

Hi wanted to display repeated elements of a Random array whose size can be specified by the user. The problem I am getting in the output is , the function is printing a repeated number as many times as it has been repeated but I want to print it only once.
Here is my code and output following the former:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 0;
}
free(repeats);
}
Here is the output I am getting
Enter the size of the array:
5
What's in the array:
3 1 2 0 3
3 occurs 2 times
3 occurs 2 times
I want "3 occurs 2 times" to print once.
Please help!
What's happening is that your code realizes 3 is repeated twice, in this block:
for(i=0;i<n;i++){
for(j=0;j<n;j++){
if(a[i] == a[j]){
count++;
}
}
if(count>1){
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
}
When i is equal to 0, it will look at the array and realize that 3 is repeated, so count>1 will be true. Then, when i is equal to 4, count>1 will be true again, and you get the double print.
In order to fix this, I would create an array that stores the numbers that have already been verified as repeated and check against that.
Since in your case, value of elements < size_array, so can take this approach.
memset(repeats, 0, n*sizeof(repeats[0]));
for(i=0;i<n;i++){
for(j=0;j<n;j++){
count = repeats[a[i]];
if(count>0)
break;
if(a[i] == a[j]){
count++;
}
}
repeats[a[i]] = count;
The idea is to store the count for each value and check before starting search for each new value to check if it has already been counted.
Try it:
for(i=0;i<n-1;i++)
{
for(j=1;j<n;j++)
{
So, don't compare the same one element with itself.
Thanks guys I got it working with the above ideas!
here is what I got..
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int array_size = 0;
int *my_array;
int i = 0;
printf("Enter the size of the array:\n");
scanf("%d",&array_size);
my_array = malloc(array_size * sizeof my_array[0]);
if(NULL == my_array) {
fprintf(stderr,"MEMORY ALLOLCATION FAILED \n");
return EXIT_FAILURE;
}
for(i=0;i<array_size;i++){
my_array[i] = rand()%array_size;
}
printf("What's in the array:\n");
for(i = 0;i<array_size;i++){
printf("%d ",my_array[i]);
}
printf("\n");
display_repeats(my_array, array_size);
free(my_array);
return EXIT_SUCCESS;
}
void display_repeats(int *a,int n){
int *freq;
freq = malloc(n * sizeof freq[0]);
int i=0;
int j=0;
int count = 0;
for(i=0;i<n;i++){
freq[i] = -1;
}
for(i=0;i<n;i++){
count = 1;
for(j=i+1;j<n;j++){
if(a[i]==a[j]){
count++;
freq[j] = 0;
}
}
if(freq[i]!=0){
freq[i] = count;
}
}
for(i=0;i<n;i++){
if(freq[i]!=1 && freq[i]!=0){
printf("%d occurs %d times\n",a[i],freq[i]);
}
}
free(freq);
}
In display_repeats(), you may simply update 2 lines and add 3 lines to make your program have the correct behaviour. And we will see it later: we can optimize the final code using C99 syntax and the comma C operator, to write far less lines than your original code (9 lines instead of 20 lines!).
So, in this answer, you will find how to get the final code that has the correct behaviour and is very short, shorter than your initial code:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
The idea is to set to -1 each array value that has matched a previous one, just after the count increment. Because you do not want to count this value again.
So simply do the following:
In the two lines where you write count = 0, replace 0 by 1, because you are sure that each number in the list must be counted at least one time.
This way, you can avoid checking the case where i equals j in the inner loop: it is already taken into account in count. So add if (i == j) continue; at the beginning of the inner loop.
With the previous updates, you are now sure that when you increment count, in the inner loop, j is not equal to i. Therefore, you can change the value of a[j] without changing a[i], in the array.
So, add a[j] = -1; just after having increased count. This way, when i will be incremented to check for a new count of a new value, it is impossible that the new counted value has already been counted.
Finally, you do not want to count how many times -1 is in the array. But you have replaced some values with -1. So simply add if (a[i] == -1) continue; at the beginning of the outer loop to avoid counting how -1 there are in the array.
This intermediate code is:
void display_repeats(int *a,int n) {
int *repeats;
repeats = malloc(n * sizeof repeats[0]);
int i=0;
int j=0;
int count = 1;
for(i=0; i<n; i++) {
if (a[i] == -1) continue;
for(j=0; j<n; j++) {
if (i == j) continue;
if(a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if(count > 1) {
repeats[i] = count;
printf("%d occurs %d times\n",a[i],repeats[i]);
}
count = 1;
}
free(repeats);
}
Now, we can optimize this code.
First, we can avoid testing a[i] == a[j] when j <= i: if such a case happens, we know that we have previously displayed the count for a[j] (the number of times a[j] appears in the array). Therefore we can replace for (j=0; j < n; j++) { by for (j=i+1; j<n; j++) {.
With this last update, we know that the first line of the inner loop will never match: i can not be equal to j. So we can remove this line (if (i == j) continue;).
Note that the values stored in the repeats array are only used to get the value of count in the printf() call. So we can remove every reference to the repeats array and simply use count in the printf() call.
Now, you can see that we set count to 1, two times. We can do it only one time, if we do not set it to 1 at the end of the main loop, to prepare a new loop, but at the beginning.
Now, note that i, j and count have the same type, so only one line may be used to define them: int i = 0, j = 0, count = 1;. More over, i and j are defined later in the for loops, so no need to define their initial value here. So we can simply write int i, j, count = 1;. But count is now defined at the beginning of the outer loop, so we do not need to define it previously. So we only need to define i, j and count without an initial value: int i, j, count;.
The new intermediate code is:
void display_repeats(int *a, int n) {
int i, j, count;
for (i = 0; i < n; i++) {
if (a[i] == -1) continue;
count = 1;
for(j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using C99 syntax
But we can do more, using the C99 specification: we can define a variable with the for instruction: we can write for (int i = ...). No more need to define it previously. So we can avoid having to write int i, j, count;, we will define them at first use:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for(int j = i + 1; j < n; j++) {
if (a[i] == a[j]) {
count++;
a[j] = -1;
}
}
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}
Using the comma C operator
Again, we can do much better! We can use the comma operator (,): it is a binary operator that evaluates its first operand, discards the result, evaluates the second operand and returns its value. Using the comma operator, we can transform count++; a[j] = -1; to a single instruction: a[j] = (count++, -1). But we can avoid the parenthesis writing count++, a[i] = -1. Now, we do not need a block for the if statement, since there is only one instruction. Therefore, we can remove a lot of parenthesis.
The final code is:
void display_repeats(int *a, int n) {
for (int i = 0; i < n; i++) {
if (a[i] == -1) continue;
int count = 1;
for (int j = i + 1; j < n; j++)
if (a[i] == a[j]) count++, a[j] = -1;
if (count > 1) printf("%d occurs %d times\n", a[i], count);
}
}

I want to print out the following to the console

I want to print out the following to the console:
+++++
++++*
+++**
++***
+****
*****
I am a new learner of programming, so encountering some difficulties. Can anyone help me, please? I have tried this, but is incorrect. What do I need to change?
#include<stdio.h>
int main(){
int i, j, k;
for(i=0; i<5; i++){
for(j=i; j<5; j++){
for(k=0; k<j; k++){
printf("*");
}
printf("+");
}
printf("\n");
}
return 0;
}
You have the right idea: Use three for loops.
#include <stdio.h>
int main() {
for (int i = 0; i < 6; i++) {
for (int k = i; k < 5; k++) {
printf("+");
}
for (int j = 0; j < i; j++) {
printf("*");
}
printf("\n");
}
return 0;
}
Test
+++++
++++*
+++**
++***
+****
*****
Online demo
First, generalise it and wrap it in a function. You want a square with a diagonal. It has to be an even number of characters to look right. But + and * could be any character, and the size could be 6 or all the way up to screen maximum width.
so
/* print a square with a diagonal
N - the size of the sides of the square
cha - character a (eg '+')
chb - character b (eg '*')
*/
void printdiagsquare(int N, char cha, char chb);
That's our prototype, and that's half the battle.
Now we need to check N is even and positive, then write the loops.
Let's get the test away first.
if(N < 2 || (N % 2) == 1)
printf(N must be even\n");
Now the main loop for each line
for(i=0;i<N;i++)
{
//printline code here
printf("\n");
}
Now test it. Is it printing N blank lines?
main(void)
{
printdiagsquare(6, '+', '*');
}
Now to get the lines printed.
to print N-1 '+'s is easy. We need j as the counter since i is the outer
for(j=0;j<N-1;j++)
printf("%c", cha);
But we need to generalise, we need to print 6,, 5, 4, 3 and so on as i increases.
So
for(j=0;j<N-i-1;j++)
printf("%c", cha);
I'll leave the last little bit for you to do. No point just typing ina function blindly.
You could try more optimized code for m-rows and n-columns
in 2 for loop only :-
#include <stdio.h>
int main(void) {
int m = 6; // Rows
int n = 5; // Cols
int i,j,k;
for (i = 0; i < m; i++) {
k = i;
for (j = n; j >= 0; j--) {
if(k>=j)
printf("*");
else
printf("+");
}
printf("\n");
}
return 0;
}

If entered an even number of integers in bubble sort program a random number is inserted in the middle

I have a task to sort negative and positive numbers while using dynamic memory, therefore in this case I used calloc and bubble sort to arrange negative numbers first while not changing their order. The problem is when I enter an even number of integers, in the middle of the result some random negative number of 10 digits appears. The same doesn't happen with odd number of integers. What seems to be the problem?
#include <stdio.h>
#include <stdlib.h>
#define SIZE 1000
void swap(int *arr, int n) {
int i, j, temp;
for (i = 0; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (arr[j] < 0) {
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
printf("sorted integers to negative and positive: \n");
for (i = 0; i < n; i++) {
printf("%i ", arr[i]);
}
}
int main() {
int n;
int i, *sk;
printf("Enter integer: \n");
scanf("%d", &n);
printf("Enter %i integers: \n", n);
sk = (int*)calloc(sizeof(int), n);
for (i = 0; i < n; i++) {
scanf("%d", sk + i);
}
swap(sk, n);
return 0;
}
This is undefined behavior that happens to manifest itself to you only when you happen to enter an even number of integers, but in reality the problem is always there: you read a value from one-past-the-end of the array, and it makes its way to the middle of your array.
You can fix this behavior by changing i <= n and j <= n with i < n and j < n. However, this is not going to fix your broken sorting algorithm, because the swapping condition is incorrect as well. Instead of
if(arr[j]<0)
it should be
if(arr[j]<arr[j-1])
You have 2 classic bugs in your for loops:
for (i = 0; i <= n; i++) is almost always wrong because the loop is run n + 1 times, where it should only enumerate index values from 0 to n - 1.
You have the same off by one error in the second loop: the test j <= n makes you go one step too far and read beyond the end of the array. Some random value gets shuffled into the array, but this undefined behavior could have worse consequences.
Furthermore, your comparison test is incorrect, it should be if (arr[j] < arr[j-1]).
As a rule of thumb, whenever you see the <= operator in a loop test, look again, it is probably a bug.
Here is a corrected version:
void swap(int *arr, int n) {
int i, j, temp;
for (i = 0; i < n; i++) {
for (j = 1; j < n; j++) {
if (arr[j] < arr[j - 1]) {
temp = arr[j];
arr[j] = arr[j - 1];
arr[j - 1] = temp;
}
}
}
printf("sorted integers to negative and positive: \n");
for (i = 0; i < n; i++) {
printf("%i ", arr[i]);
}
printf("\n");
}

Error in function for Selection-Sort

My code for selection-sort
#include <stdio.h>
void selection_sort(int a[], int n);
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d",&size);
int b[size],i = 0;
printf("Enter %d integers to be sorted: ",size);
while(i++ < size)
scanf("%d",&b[i]);
selection_sort(b, size);
printf("Sorted integers(by selection sort) are: ");
for(int i = 0; i < size; i++)
printf("%d",b[i]);
return 0;
}
void selection_sort(int a[], int n)
{
while(n >= 0 )
{
if(n == 0)
break;
else
{
int i = 0, c = 0;
int largest = a[0];
while(i++ < n)
if(largest < a[i])
{
c = i ;
largest = a[i];
}
int temp = a[--n];
a[n] = largest;
a[c] = temp;
selection_sort(a, n);
}
}
}
on sorting the array in ascending order
3 4 1 2
is giving weird output
2293388 4 3 0
I checked this many time but failed to remove the problem.
What should I do to work it properly?
Algorithm used :
1. search for largest element in the array.
2. Move largest element to the last position of array.
3. Call itself recursively to sort the first n -1 element of the array.
Please don't give any other solution otherwise I will get confused.
EDIT
Ah, I see what goes wrong. First of all, while (i++ < n) does not do exactly what you expect it to do. It checks if the condition i < n is true, then it increments i. However, it seems that after the conditional check, i is already incremented in the body. So for example,
while (i++ < n)
printf ("%d ", i);
will print out (with n=4):
1 2 3 4
So you first need to change that. Secondly, the outer while-loop is not at all necessary. Using one loop will suffice. Again, change the while loop in here to while (i < n) and increment i in the body. SO the final code will be:
#include <stdio.h>
void selection_sort(int a[], int n);
int main()
{
int size;
printf("Enter the size of array: ");
scanf("%d", &size);
int b[size], i = 0;
printf("Enter %d integers to be sorted: ", size);
while(i < size) {
scanf("%d", &b[i]);
i++;
}
selection_sort(b, size);
printf("Sorted integers(by selection sort) are: ");
i = 0;
for(i = 0; i < size; i++)
printf("%d ", b[i]);
printf ("\n");
return 0;
}
void selection_sort(int a[], int n)
{
if(n == 0)
return;
else
{
int i = 0, c = 0;
int largest = a[0];
while(i < n) {
if(largest < a[i])
{
c = i;
largest = a[i];
}
i++;
}
int temp = a[--n];
a[n] = a[c];
a[c] = temp;
selection_sort(a, n);
}
}
I tested this with your given input (3 4 1 2) and it prints out a sorted list: 1 2 3 4.
Whenever you see such weird big numbers, its usually an array out of bounds issue. Please take a small data-set, say 5-6 numbers, and walk through your program. I am sure you can fix it. Good luck!!

Resources