How to use dynamic arrays? - c

Q: Find all prime numbers between two given Numbers a and b, by using Sieve of Eratosthene.
Im using dynamic array to store prime numbers, but it does nt work.
After debug it, everything is ok untill the last
printf() that crashes.
Code
int main() {
int i, j, n, a, b, k;
int *tab;
scanf("%i", &n); // n is number of sets
for (i = 1; i <= n; i++){
scanf("%i %i", &a, &b);
tab = (int*) malloc(b * sizeof(int)); //allocating the memorry
for (j= 0; j < b; j++){ //seting all numbers to be prime
*(tab + j) = 1;
}
for (j = 2; j <= b; j++){
if (*(tab + j) == 1){
for(k = j; k <= b; k+=j)
*(tab + k) = 0; //seting 0 for all non prime numbers
}
}
for (j = a; j <= b; j++){
if (*(tab + j) == 1){
printf("%i", j); //printing prime numbers
}
}
free(tab);
}
return 0;
}

your second loop should be
for (j = 2; j <= b; j++){
if (*(tab + j) == 1){
for(k = j; k <= b; k += j)
*(tab + k) = 0; //seting 0 for all non prime numbers
}
}
the problem was that because you used multiplication, you tried to access an item in the tab array with index above its allocated size.
edit: and as #melpomene stated, the array is too short. therefore the allocation should be
tab = (int*) malloc((1+b) * sizeof(int));

The problem is, you're accessing array out of its bounds:
*(tab + k*j) = 0;
when
k <= b
j <= b
When you declare array of b elements, you can only access array from 0 to b-1 index.
BTW, as mentioned in comments, using tab[k*j] is more readable and shows clearly that tab is array.
I don't really understand what you mean by sets number, but pseudocode of Sieve of Eratosthenes taken from wiki is applied from 2 to n. So in your case 2 becomes a and n becomes b. You don't need checking all numbers from a to b, root of b will suffice.
Your algorithm should look like:
create array for holding b - a elements
make every element equals 1
make 0 elements which fulfill Eratosthenes rules for complex number
print indexes which contains 1.

Related

how to list all pairs of sexy primes

How can i write a program that lists all sexy prime pairs that exist in n numbers.
For example if n = 10 the output should be (5, 11) and (7, 13)
My idea was to generate all primes within n and then add 6 to each and check if the i + 6 is a prime. But it doesnt work, there's no output and the program ends.
#include <stdio.h>
int main() {
int i, j, n, k, isprime = 1, prime2, flag = 0;
scanf("%d", &n);
for (i = 3; i <= n; i++){
for (j = 2; j <= i; j++){
if (i % j == 0)
break;
}
if (i == j){
prime2 = i + 6;
for (k = 3; k <= prime2; k++){
if (prime2 % k == 0){
flag++;
break;
}
}
if (flag == 0){
printf("%d %d\n", i, prime2);
}
}
}
return 0;
}
Any ideas of what im doing wrong or any tips on how to solve it? (with loops only)
As there're a lot of resources about finding a prime number, I'm not going to discuss that. Rather I'll try to point out the bug in your code.
First problem:
for (k = 3; k <= prime2; k++)
Here you need to run the loop till prime2 - 1. Also you should start checking from 2 rather than 3, just like you did previously. That means,
for (k = 2; k < prime2; k++)
or
for (k = 2; k <= prime2 - 1; k++)
Reason: when k = prime2, prime2 % k will be 0. For finding out whether a number is prime we don't need to check if that number is divisible by 1 and that number itself.
Note: Now you might think why the first prime number loop for (j = 2; j <= i; j++) is working .
It's working because you've given an additional condition if (i == j) after it.
Second problem:
You need to declare the flag variable within the first loop.
for (i = 2; i <= n; i++)
{
int flag = 0;
.... (rest of the code)
....
}
Reason: Basically with the flag value, you're trying to find out whether prime2 is a prime number.
Every time you'll get a prime number from the first loop, you'll have a new value of prime2. In your code, once you're incrementing the value of flag, you're never resetting the flag value.
That's why once your code detects a prime2 which is not a prime, it'll never detect the second prime number again (prime2 which is actually prime).
Overall code:
#include <stdio.h>
int main()
{
int i, j, n, k, isprime = 1, prime2;
scanf("%d", &n);
for (i = 3; i <= n; i++)
{
int flag = 0; // changing point
for (j = 2; j <= i; j++)
{
if (i % j == 0)
break;
}
if (i == j)
{
prime2 = i + 6;
for (k = 2; k < prime2; k++) // changing point
{
if (prime2 % k == 0)
{
flag++;
break;
}
}
if (flag == 0)
{
printf("%d %d\n", i, prime2);
}
}
}
return 0;
}
Few resources to know more about finding out prime numbers:
Prime Numbers
C Program to Check Whether a Number is Prime or not
Sieve of Eratosthenes
You can use Sieve to speed up the program. It can generate all pairs in O(N log N) time. Here's the Algorithm.
Now, you have a boolean array, is_prime where is_prime[i] is true if i is a prime, false otherwise.
Now, iterate from i = 1 to i = N and check if is_prime[i] && is_prime[i + 6], if the condition is true, output the pair.

Minor changes in indexing take twice memory and time

I submitted two slightly different solutions for a problem in which you have remove duplicate elements of an array, so that the relative order does not change.
In first method, I take input sequentially, and store in an array sequentially, and then two nested loops, to check for each element in input array, if it is unique, I store it in another array.
While in second method, I take input sequentially, but store then in reverse order. Rest is same, except the required indexing/iterator changes.
The second one takes twice as much time and memory as first.
Though, the difference is very minor, then why is there a huge difference in time?
Or How can I check exactly why is there this difference?
Actual Problem: You are given an array a consisting of n integers. Your task is to make these array unique by removing duplicates from them.
You have to leave only the rightmost occurrence for each element of the array and remove all other occurrences. The relative order of the remaining unique elements should not be changed.
First method (15 ms, 4 KB):
#include <stdio.h>
int main(void)
{
int n, i, c;
scanf("%i", &n);
int arr[n], nondupe[n];
for (i = 0; i < n; i++)
scanf("%i", arr + i); // Store sequentially
int k = n - 1;
nondupe[k--] = arr[n - 1]; // add last element in non-duplicate array (because rightmost entries are required)
for (i = n - 1; i > 0; i--)
for (c = n - 1; c > k; c--) // Nested loops to iterate over all elements in both arrays
{
if (arr[i - 1] == nondupe[c])
break;
if (c == k + 1)
nondupe[k--] = arr[i - 1];
}
printf("%i\n", n - k - 1);
for (i = k + 1; i < n; i++)
printf("%i ", nondupe[i]);
}
Second (30 ms, 8 KB):
#include <stdio.h>
int main(void)
{
int n, i, c;
scanf("%i", &n);
int arr[n], nondupe[n];
for (i = n; i > 0; i--)
scanf("%i", arr + i - 1);
int k = 0;
nondupe[k++] = arr[0];
for (i = 0; i < n; i++)
for (c = 0; c < k; c++)
{
if (arr[i] == nondupe[c])
break;
if (c == k - 1)
nondupe[k++] = arr[i];
}
printf("%i\n", k);
for (i = k; i > 0; i--)
printf("%i ", nondupe[i - 1]);
}

time-saving way to check whether numbers in an array have common factor?

The aim of this assignment is to find the number of pairs can be formed by every two number in an array. The condition is that these two number can not have common factors.
I have tried using loop comparing number by number in an array with a loop of factor starts from 2. This code works but it exceeds the time limit for 2 out of 10 cases on codecrunch.
double estimate_PI(int list[], int size) {
int i, pair;
pair = size * (size - 1) / 2; //total number of pairs can be formed
int count = pair;
int j, l;
for (i = 0; i < size; i++) { //check the first number in the array
for (j = i + 1; j < size; j++) { //check compare the first number of the rest
// of the numbers in the array
for (l = 2; l < list[j]; l++) { //check for common factors
if (list[i] % l == 0 && list[j] % l == 0) { //if these two values have common factor
count--; //the possible number of pair reduce by 1
break;
}
}
}
}
// printf("%d\n count",count);
double PI = sqrt(6.0000 * pair / count);
return PI;
}
For this method it takes too long for the codecrunch to run and it mark me wrong.
Rather than try every value [2...list[j]), perhaps look for the Greatest common divisor
Example int gcd(int a, int b) Arjun Sreedharan or chux
#if 0
for (l = 2; l < list[j]; l++) { //check for common factors
...
}
#else
if (gcd(list[i], list[j]) <= 1) count--;
#endif
Simplification possible as only the first factor > 1 needs to be found.

Is it the efficeint program to rotate array in left direction?

#include<stdio.h>
#include<stdlib.h>
main()
{
int i,j,l,m,n;
j=0;
printf("\nenter 5 element single dimension array\n");
printf("enter shift rate\n");
scanf("%d",&n);
/* Here we take input from user that by what times user wants to rotate the array in left. */
int arr[5],arrb[n];
for(i=0;i<=4;i++){
scanf("%d",&arr[i]);
}
/* Here we have taken another array. */
for(i=0;i<=4;i++){
printf("%d",arr[i]);
}
for(i=0;i<n;i++){
arrb[j]=arr[i];
j++;
// These loop will shift array element to left by position which's entered by user.
}
printf("\n");
for(i=0;i<=3;i++){
arr[i]=arr[i+n];
}
for(i=0;i<=4;i++){
if(n==1 && i==4)
break;
if(n==2 && i==3)
break;
if(n==3 && i==2)
break;
printf("%d",arr[i]);
}
//To combine these two arrays. Make it look like single array instead of two
for(i=0;i<n;i++){
printf("%d",arrb[i]);
}
// Final sorted array will get printed here
}
Is it the efficeint program to rotate array in left direction?
Actually, very complicated, and some problems contained:
for(i = 0; i < n; i++)
{
arrb[j] = arr[i];
j++;
}
Why not simply:
for(i = 0; i < n; i++)
{
arrb[i] = arr[i];
}
There is no need for a second variable. Still, if n is greater than five, you get into trouble, as you will access arr out of its bounts (undefined behaviour!). At least, you should check the user input!
for(i = 0; i <=3 ; i++)
{
arr[i] = arr[i + n];
}
Same problem: last accessible index is 4 (four), so n must not exceed 1, or you again access the array out of bounds...
Those many 'if's within the printing loop for the first array cannot be efficient...
You can have it much, much simpler:
int arr[5], arrb[5];
// ^
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5];
This does not cover negative values of n, though.
arrb[i] = arr[(((i + n) % 5) + 5) % 5];
would be safe even for negative values... All you need now for the output is:
for(int i = 0; i < 5; ++i)
printf("%d ", arrb[i]);
There would be one last point uncovered, though: if user enters for n a value greater than INT_MAX - 4, you get a signed integer overflow, which again is undefined behaviour!
We can again cover this by changing the index formula:
arrb[i] = arr[(5 + i + (n % 5)) % 5];
n % 5 is invariant, so we can move it out of the loop:
n %= 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(5 + i + n) % 5];
Finally, if we make n positive already outside, we can spare the addition in the for loop.
n = ((n % 5) + 5) % 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5]; // my original formula again...
Last step is especially worth considering for very long running loops.
I think you want to do something like this (you should check that 0 <= n <= 5, too):
int b[5];
int k = 0;
for(i=0; i<5; i++){
if (i < 5 - n)
b[i] = arr[i+n];
else
{
b[i] = arr[k];
k++;
}
}
Array b is used to save the rotated matrix.

in C ,why result is different after only changing loop boundary?

I met this problem when verifying whether points in a finite field GF(13) is on elliptic curve y^2 = x^3 + x + 1:
first I set the loop boundary as i<2,the results came out right.
#include <stdio.h>
#include <math.h>
void main ()
{
int a[13], b[13];
int j, i, m, k = 0;
for (i = 0; i < 2; i++)
for (j = 0; j < 13; j++)
if ((i * i * i + i + 1) % 13 == (j * j) % 13) {
a[k] = i;
b[k] = j;
k++;
}
printf ("\n There are %d points on the curve\nThe points are: ", k);
for (m = 0; m < k; m++)
printf ("\nx=%d,y=%d \n", a[m], b[m]);
}
The result is link 1
after I change the i<2 to i<13,
for(i=0;i<13;i++)
the first 4 points changed: link 2
You are entering undefined behavior. If you set a break inside the loop you will notice that k >= 13 which is outside the bounds of your arrays.
You could add some bounds checking and consider the size of your arrays.

Resources