I am writing a program that creates two vectors to practice comparing elements in a vector. The first vector is a list of all numbers that are not prime numbers between 1-100 (not prime numbers), the second vector is a list of all numbers between 1-100 (vector number_bank). I am using loops to compare each element in the vectors. Lets say the number 5 comes up from the number_bank (which is a prime number), if this number does not match any number in the not_prime_numbers vector then it is pushed back into a third vector called prime numbers. If a number like 4 were to be compared to the elements of the not_prime_number list it is supposed to match with the number 4 in this list and break the loop without pushing back the number into the prime_numbers vector. What is happening is all numbers between 1-100 are being pushed back. 4 in the number_bank vector is never equal to the 4 in the not_prime_numbers vector so the cycle continues pushing back 4 into the prime numbers vector.
There is no math involved changing the elements in these vectors so there shouldn't be an incremental margin of error (epsilon) usually associated with comparing floats. Is there a better way to compare the elements in these vectors?
int main()
{
float i = 1.0;
unsigned int n = 0;
std::vector<float>not_prime_numbers;
std::vector<float>number_bank;
std::vector<float>prime_numbers;
while (i < 101.0)
{
for (float j = 1.0;j<(i);++j)
{
float p = i / j;
if (abs(floor(p)) == p&&j!=1.0)
{
not_prime_numbers.push_back(i);
break;
}
}
++i;
}
for (float k = 1.0; k < 101.0; ++k)
{
number_bank.push_back(k);
}
for (unsigned int m = 0; m < number_bank.size(); ++m)
{
while (n < not_prime_numbers.size())
{
if (not_prime_numbers[n] == number_bank[m]) // here is where i try to break the loop
{
break;
}
if (n == (not_prime_numbers.size()-1))
{ // here is where element is pushed back when compared to all loop elements
prime_numbers.push_back(number_bank[m]);
break;
}
if (not_prime_numbers[n] != number_bank[m])
{
++n;
}
}
}
std::cout << "All prime numbers between 0 and 100 are as follows:\n";
for (unsigned int j = 0; j < prime_numbers.size(); ++j)
{
std::cout << prime_numbers[j] << "\n";
}
return 0;
}
I read about .compare and tried it but it states that there needs to be a class structure to the left (perhaps a vector has no class structure?). I'm new to C++ and would greatly appreciate the help.
You never reset n, so once you get a prime number (when n == (not_prime_numbers.size()-1)) the rest of the numbers will also be added to the prime list.
Why are you checking that condition within the loop? You should set a flag variable if you find the number is not prime, then check that after your loop to possibly add it to your prime list.
Related
I have an array a[n]. The number n is entered by us. I need to find the minimal product of a[i] and a[j] if:
1) abs(i - j) > k
2) a[i] * a[j] is minimised
Here is my solution (very naive):
#include <iostream>
using namespace std;
#define ll long long
int main() {
ll n,k; cin >> n >> k;
ll a[n]; for(ll i=0;i<n;i++) cin >> a[i];
ll mn; bool first = true;
for(ll i=0;i<n;i++) {
for(ll j=0;j<n;j++) {
if(i!=j)
if(abs(i-j) > k) {
if(first) {
mn = a[i]*a[j];
first = false;
} else if(a[i]*a[j] < mn) mn = a[i]*a[j];
}
}
}
cout << mn << endl;
}
But I want to know if there is any faster way to find a minimal product with distance?
Assuming there is at least one pair of elements satisfying the conditions and no multiplication of two elements in it overflows, this can be done in Theta(n-k) time and Theta(1) space worst- and best-case, with something like this:
auto back_max = a[0];
auto back_min = a[0];
auto best = a[0]*a[k+1];
for(std::size_t i=1; i<n-(k+1); ++i) {
back_max = std::max(back_max, a[i]);
back_min = std::min(back_min, a[i]);
best = std::min(best, std::min(a[i+k+1]*back_max, a[i+k+1]*back_min));
}
return best;
This is optimal in terms of asymptotic worst-case complexity for both time and space because the optimal product may be a[0] with any of the n-(k+1) elements in distance at least k+1, so at least n-(k+1) integers need to be read by any algorithm solving the problem.
The idea behind the algorithm is as follows:
The optimal product uses two elements of a, assume these are a[r] and a[s]. Without loss of generality we can assume that s > r since the product is commutative.
Due to the restriction abs(s-r) > k this implies that s >= k+1. Now s could be each of the indices satisfying this condition, so we iterate over these indices. That is the iteration over i in the shown code, but it is shifted by k+1 for convenience (doesn't really matter). For each iteration we need to find the optimal product involving i+k+1 as largest index and compare it with the previous best guess.
The possible indices to pair i+k+1 with are all indices smaller or equal i due to the distance requirement. We would need to iterate over all of these as well, but that is unnecessary because the minimum of a[i+k+1]*a[j] over j at fixed i is equal to min(a[i+k+1]*max(a[j]), a[i+k+1]*min(a[j])) due to monotonicity of the product (taking the minimum with respect to both the minimum and maximum over a[j] accounts for the two possible signs of a[i+k+1] or equivalently the two possible directions of monotonicity.)
Since the set of a[j] values over which we optimize here is just {a[0], ..., a[i]}, which simply growths by one element (a[i]) in each iteration of i, we can simply keep track of max(a[j]) and min(a[j]) with single variables by updating them if a[i] is larger or smaller than the previous optimal values. This is done with back_max and back_min in the code example.
The first step of the iteration (i=0) is skipped in the loop and instead performed as initialization of the variables.
Not sure about fastest.
For the simpler problem without i < j - k, the minimal product is among the products of pairs from the two smallest and largest elements.
So, (the following is too complicated, see walnut's answer)
( • balk if k ≤ n
• initialise minProduct to a[0]*a[k+1])
keep two dynamic minmax data structures upToI and beyondIplusK
starting with { } and { a[j] | k ≤ j }
for each i from 0 to n - k - 1
add a[i] to upToI
remove a[i+k] from beyondIplusK
check for new minimal product among
min(upToI)×min(beyondIplusK), min(upToI)×max(beyondIplusK),
max(upToI)×min(beyondIplusK) and max(upToI)×max(beyondIplusK)
For "minimum magnitude"
Find the 2 "smallest magnitude" elements, then (after you've either found two zeros or searched the whole array), multiply them.
For "lowest value" without the abs(i - j) > k part
There are 3 possibilities:
the two highest (smallest magnitude) negative numbers
the two lowest (smallest magnitude) non-negative numbers
the lowest (largest magnitude) negative number and the highest (largest magnitude) non-negative number
You could search for all 6 values and figure out the products and which is best at end.
However; as soon as you see a zero you know you don't need to know any more about the first 2 possibilities; and as soon as you see one negative number and one non-negative number you know that you only care about the third possibility.
This leads to a finite state machine with 3 states - "care about all 3 possibilities", "answer is zero unless a negative number is seen" and "only care about the last possibility". This can be implemented as a set of 3 loops, where 2 of the loops jump into (goto) the middle of another loop when the state (of the finite state machine) changes.
Specifically, it might looks something vaguely like (untested):
// It could be any possibility
for(ll i=0;i<n;i++) {
if(a[i] >= 0) {
if(a[i] < lowestNonNegative1) {
lowestNonNegative2 = lowestNonNegative1;
lowestNonNegative1 = a[i];
}
if(lowestNonNegative2 == 0) {
goto state2;
}
} else {
if(a[i] > highestNegative1) {
highestNegative2 = highestNegative1;
highestNegative1= a[i];
}
if(lowestNonNegative1 < LONG_MAX) {
goto state3;
}
}
}
if(lowestNonNegative2 * lowestNonNegative1 < highestNegative2 * highestNegative1) {
cout << lowestNonNegative2 * lowestNonNegative1;
} else {
cout << highestNegative2 * highestNegative1;
}
return;
// It will be zero, or a negative and a non-negative
for(ll i=0;i<n;i++) {
state2:
if(a[i] < 0) {
goto state3;
}
}
cout << "0";
return;
// It will be a negative and a non-negative
for(ll i=0;i<n;i++) {
state3:
if(a[i] < lowestNegative) {
lowestNegative = a[i];
} else if(a[i] > highestNonNegative) {
highestNonNegative = a[i];
}
}
cout << lowestNegative * highestNonNegative;
return;
For "lowest value" with the abs(i - j) > k part
In this case you still have the 3 possibilities; and could make it work with the same "3 loops with finite state machine" approach but it gets too messy/ugly. For this case a better alternative is likely to pre-scan the array to determine if there are any zeros and if they're all negative or all positive; so that after the pre-scan you can either know the answer is zero or select a loop designed for the specific possibility alone.
This question already has answers here:
Sieve of Eratosthenes algorithm
(14 answers)
Closed 3 years ago.
The Prime Generator requires prime numbers between a certain range.
Input :
The input begins with the number t of test cases in a single line (t<=10). In each of the next t lines there are two numbers m and n
(1 <= m <= n <= 1000000000, n-m<=100000) separated by a space.
Output :
For every test case print all prime numbers p such that m <= p <= n, one number per line, test cases separated by an empty line.
My program runs perfectly with this solution but the time limit is exceeded and it isn't accepted as a solution.
I've replaced cin and cout with scanf and printf.
I've replaced for loops with while loops and what not. What other measures can I take to speed up my solution?
#include<iostream>
int prime(unsigned long int p)
{
int f=1,i=2;
while(i<=p/2)
{
if(p%i==0)
{ f=0;
break;
}
++i;
}
if(f==1)
{ printf("%d \n",p);
}
return 0;
}
int main()
{
int t, i=0;
unsigned long int m,n,j;
scanf("%d",&t);
while(i<t)
{
scanf("%lu%lu",&m,&n);
for(j=m;j<=n;++j)
{
if(j!=1&&j!=0)
prime(j);
}
printf("\n");
++i;
}
return 0;
}
Your code is inefficient because you’re using a slow algorithm to find primes. Changing a for loop to a while loop probably won’t speed up the code, but changing to a better algorithm will.
A faster algorithm:
There’s a really simple algorithm called the Sieve of Eratosthenes. We start out by making an array of bools. Mark all of them true. This array will let us keep track of which numbers are and aren’t prime. We’re gonna cross out the ones we know aren’t prime (by setting them to false).
Cross out 0 and 1 from the array
Starting with 4, cross out all numbers that are multiples of 2
Starting with 6, cross out all numbers that are multiples of 3
Starting with 10, cross out all multiples of 5
Starting with 14, cross out all multiples of 7
(Continue this process)
Example:
// takes a reference to a vector of bools
// a vector is a resizable array
void cross_out_multiples(std::vector<bool>& primes, int num) {
for(int i = num * 2; i < primes.size(); i += num) {
primes[i] = false;
}
}
std::vector<int> findPrimes(int max) {
std::vector<bool> primes(max); // create array with max elements
for(int i = 0; i < max; ++i) {
primes[i] = true;
}
// 0 and 1 aren’t prime, so we mark them false
primes[0] = false;
primes[1] = false;
// here we mark multiples of n false
for(int n = 2; n < max; n++) {
// if a number isn’t prime, we can skip it
if(not primes[n]) {
continue;
}
// if n squared is bigger than max, we already
// crossed out all multiples of n smaller than max
// so we don’t have any more work to do
if(n * n > max) {
break;
}
// now we just cross out multiples of n
cross_out_multiples(primes, n);
}
// now, take the numbers that are prime:
std::vector<int> listOfPrimes;
for(int i = 0; i < max; i++) {
// if a number is prime, add it to the list
if(primes[i]) {
listOfPrimes.push_back(i);
}
}
return listOfPrimes;
}I
Your code is correct, but (very) inefficient. The online judge not only requires correctness, but also efficiency.
The simple scanning algorithm of yours can be immediately made faster by two simple measures:
only test odd divisors
only test divisors up to sqrt(p) (which for large p is much smaller than p/2)
But ultimately learn about the sieve of Eratosthenes.
So, I have a cycle that goes over an array and should reverse the sequence of consecutive positive numbers, but it seems to count excess negative number as a part of a sequence, thus changing its position. I can't figure the error myself, and will be happy to hear any tips!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
int Arr[100];
int Arr2[100];
int main()
{
srand(time(NULL));
int n, x;
bool seq = false;
int ib = 0;
printf("Starting array\n");
for (n = 0; n < 100; Arr[n++] = (rand() % 101) - 50);
for (n = 0; n < 100; printf("%3d ", Arr[n++]));
putchar('\n');
for (n = 0; n < 100; n++) //sorting
{
if (Arr[n] > 0) //check if the number is positive
{
if (seq == false) //if it isn't the part of a sequence
{
seq = true; ib = n; //declare it now is, and remember index of sequence's beginning
}
else
seq = true; //do nothing if it isn't first
}
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
seq = false; //declaring sequence's end
Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array
}
}
printf("Modified array\n");
for (n = 0; n < 100; printf("%3d ", Arr2[n++]));
putchar('\n');
system('pause');
return 0;
}
following what we discussed in comments, i listed couple of rules here to shape my answer around it.
Rules :
the sequence of elements can be varied. so if there are 5 positive numbers in a row within an array, we would be reversing the 5 elements. for example
array[5] = {1,2,3,4,5} would become array[5]{5,4,3,2,1}
if single positive number neighboured by negatives, no reverse can happen
array[4] = {-1,0,-2,1} would result the same array
no processing happens when a negative number is discovered.
based on these rules.
here is what I think going wrong in your code.
Problems :
1- consider thisarray = {1,2,-1}. notice that the last value is negative. because of this. the following code would run when the 3rd index of the array is processed;
` Arr2[n + 1] = Arr[n + 1]; //assigning negative numbers at the same place of a new array`
this is a no-no. since you are already at the end of the Arr2 n+1 would indicate that there is a 4th element in the array. (in your case 101h element of the array) this would cause an undefined behaviour.
2 - consider the same array mentioned above. when that array is looped, the outcome would be array = {-1,2,1} . the -1 and 1 are swapped instead of 1 and 2.
3 - you are assigning ib = n whenever a negative number is found. because whenever a negative value is hit, seq=false is forced. But the ib, never been put into use until a next negative number is found. here is an example;
array = {...2, 6}
in such scenario, 2 and 6 would never get reversed because there is no negative value is following this positive sequence.
4 - consider this scenario arr = {-10,-1,....} this would result in arr = {0,-1,....}. This happens because of the same code causing the undefined behaviour problem mentioned above.
`Arr2[n + 1] = Arr[n + 1];`
Suggestion
Most of the problems mentioned above is happening because you are trying to figure out the sequence of the positive numbers when a negative number is found.
else //if the number is negative
{
if (seq==true) //if sequence isn't null
for (x = n; ib <= n; ib++, x--) //new variable so that n will stay unchanged,
number of iterations = length of sequence
{
Arr2[x] = Arr[ib]; //assigning array's value to a new one,
reversing it in the process
}
you should completely get rid of that and completely ignore the negative numbers unless you forgot to mention in your question some key details. instead just focus on the positive numbers. I'm not going to send you the entire code but here is how I approached the problem. feel free to let me know if you need help and I would be more then happy to go through in detail.
start your for loop as usual.
for (n = 0; n < 100; n++) //sorting
{
don't try to do anything when an element in an array is a negative value.
if (Arr[n] > 0) //check if the number is positive
if the number is positive. create recording the sequence indices. for one, we know the sequence will start at n once the `if (Arr[n] > 0) true. so we can do something like this;
int sequenceStart = n;
we also need to know when the positive number sequence ends.
int sequenceEnd = sequenceStart;
the reason for int sequenceEnd = sequenceStart; is because we going to start using the same n value to start with. we can now loop through the array and increment the sequenceEnd until we reach to a negative number or to the end of the array.
while (currentElement > 0)
{
n++;//increment n
if(n < arraySiz) //make sure we still in the range
{
currentElement = Arr[n]; // get the new elemnet
if (currentElement > 0)
{
sequenceEnd++;
}
}
else
break; // we hit to a negative value so stop the while loop.
}
notice the n++;//increment n this would increment the n++ until we reach to the negative number. which is great because at the end of the sequence the for loop will continue from the updated n
after the while loop, you can create an array that has the same size as the number of sequences you iterated through. you can then store the elements from starting arr[sequenceStart] and arr[sequenceEnd] this will make the reversing the sequence in the array easier.
I am currently working on assignment which is stated below. My question is that why does my code only repeat prime number as 2 and not the remainder of the numbers. I would much appreciate if someone could help me to walk through the logic so i can try to solve the solution, rather than posting the answer outright. Kudos to all :)
Write a program that uses two nested for loops and the modulus
operator (%) to detect and print the prime numbers from 1 to 10,000.
(Prime numbers are natural numbers that are not evenly divisible by
any other number except for themselves and one). Display all the
primes found.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> n; // will store our values from 1-10000
for (int i= 0; i < 10000; i++) { // vector loading
n.push_back(i);
n[i]= n[i] + 1;
for (int j= 1; j < 10000 ; j++ ) { // Error is here?
if (n[j] % j == 0) { // supposed to go through all the numbers
// and flag the prime numbers
cout<<n[i] <<" is a prime";
i++;
break;
}
}
}
return 0;
}
The trivial method is rather easy to understand.
Outer loop (suppose the loop variable here is num) go through from 2 to 10000, and check every number whether it is a prime number.
Inner loop (suppose the loop variable here is fact) go through form 2 to num - 1
Check if num has a factor fact by num % fact == 0. If fact is a factor of num, then break the inner loop and continue to check the next number.
If after checking all the numbers from 2 to num - 1 and none of them is the factor of num, then we are sure that num is a prime number and continue to check the next number.
Note that 0 and 1 are special case so we exclude them from the loop.
This method doesn't need any array. The time complexity is O(n2) and space complexity is O(1).
BTW, there are other better solution to this problem, for example Sieve of Eratosthenes.
There are a couple of problems but for a starter consider the very first loop.
i = 0
n.push_back(i); // Now n[0] is now valid (having the value 0)
n[0] = n[0] + 1; // Now n[0] is still valid (having the value 1)
j = 1;
if (n[j] % j == 0) // Ups... access to n[1] which is invalid
// as you have only pushed one element, i.e. n[0]
Understand the purpose of your loops
The outer loop is the one that supplies the numbers, therefore you
don't need the vector
The inner loop is the one that does the checking
Where do you print?
The inner loop checks if a number is not prime. The only way it
knows this is if the number supplied by the outer loop is not divisible by any number supplied by the inner loop. Therefore the inner loop
does not print anything because it has to exhaust all checks before it knows that a number is prime
Your print statement should come last. This means it should be after the inner loop but still inside the outer loop and it should print the number if it is prime based on what was discovered by the inner loop. So you should have a way of knowing if the inner loop found a prime or not
Finally note that the inner loop has to start at 2 and end at i - 1 because every number is divisible by 1 and itself
Do not need to iterate through the entire range for inner loop, for inner loop there will possible values are starting from 2 to <= that number /2 .
Like if you want to check whether 99 is prime or not then you need to
set inner loop from 2 to 49 (99 / 2 is the max possible factor for
that number) so do not iterate through the rest all.
So if you iterate inner loop from 2 to 98 then it's meaning less to
iterate this loop after 49, think about it.
#include <iostream>
#include <vector>
using namespace std;
int main()
{
//vector<int> n; // will store our values from 1-10000
int flag =0;
for (int i= 2; i < 10000; i++) // vector loading
{
//n.push_back(i);
//n[i]= n[i] + 1;
flag =0;
for (int j= 2; j <= i / 2 ; j++ )
{
if (i % j == 0)
{
flag = 1;
break;
}
}
if(flag == 0)
{
cout << "%d number is Prime" << i;
}
}
return 0;
}
While trying to find prime numbers in a range (see problem description), I came across the following code:
(Code taken from here)
// For each prime in sqrt(N) we need to use it in the segmented sieve process.
for (i = 0; i < cnt; i++) {
p = myPrimes[i]; // Store the prime.
s = M / p;
s = s * p; // The closest number less than M that is composite number for this prime p.
for (int j = s; j <= N; j = j + p) {
if (j < M) continue; // Because composite numbers less than M are of no concern.
/* j - M = index in the array primesNow, this is as max index allowed in the array
is not N, it is DIFF_SIZE so we are storing the numbers offset from.
while printing we will add M and print to get the actual number. */
primesNow[j - M] = false;
}
}
// In this loop the first prime numbers for example say 2, 3 are also set to false.
for (int i = 0; i < cnt; i++) { // Hence we need to print them in case they're in range.
if (myPrimes[i] >= M && myPrimes[i] <= N) // Without this loop you will see that for a
// range (1, 30), 2 & 3 doesn't get printed.
cout << myPrimes[i] << endl;
}
// primesNow[] = false for all composite numbers, primes found by checking with true.
for (int i = 0; i < N - M + 1; ++i) {
// i + M != 1 to ensure that for i = 0 and M = 1, 1 is not considered a prime number.
if (primesNow[i] == true && (i + M) != 1)
cout << i + M << endl; // Print our prime numbers in the range.
}
However, I didn't find this code intuitive and it was not easy to understand.
Can someone explain the general idea behind the above algorithm?
What alternative algorithms are there to mark non-prime numbers in a range?
That's overly complicated. Let's start with a basic Sieve of Eratosthenes, in pseudocode, that outputs all the primes less than or equal to n:
function primes(n)
sieve := makeArray(2..n, True)
for p from 2 to n
if sieve[p]
output(p)
for i from p*p to n step p
sieve[p] := False
This function calls output on each prime p; output can print the primes, or sum the primes, or count them, or do whatever you want to do with them. The outer for loop considers each candidate prime in turn; The sieving occurs in the inner for loop where multiples of the current prime p are removed from the sieve.
Once you understand how that works, go here for a discussion of the segmented Sieve of Eratosthenes over a range.
Have you considered the sieve on a bit level, it can provide a bit larger number of primes, and with the buffer, you could modify it to find for example the primes between 2 and 2^60 using 64 bit ints, by reusing the same buffer, while preserving the offsets of the primes already discovered. The following will use an array of integers.
Declerations
#include <math.h> // sqrt(), the upper limit need to eliminate
#include <stdio.h> // for printing, could use <iostream>
Macros to manipulate bit, the following will use 32bit ints
#define BIT_SET(d, n) (d[n>>5]|=1<<(n-((n>>5)<<5)))
#define BIT_GET(d, n) (d[n>>5]&1<<(n-((n>>5)<<5)))
#define BIT_FLIP(d, n) (d[n>>5]&=~(1<<(n-((n>>5)<<5))))
unsigned int n = 0x80000; // the upper limit 1/2 mb, with 32 bits each
// will get the 1st primes upto 16 mb
int *data = new int[n]; // allocate
unsigned int r = n * 0x20; // the actual number of bits avalible
Could use zeros to save time but, on (1) for prime, is a bit more intuitive
for(int i=0;i<n;i++)
data[i] = 0xFFFFFFFF;
unsigned int seed = 2; // the seed starts at 2
unsigned int uLimit = sqrt(r); // the upper limit for checking off the sieve
BIT_FLIP(data, 1); // one is not prime
Time to discover the primes this took under a half second
// untill uLimit is reached
while(seed < uLimit) {
// don't include itself when eliminating canidates
for(int i=seed+seed;i<r;i+=seed)
BIT_FLIP(data, i);
// find the next bit still active (set to 1), don't include the current seed
for(int i=seed+1;i<r;i++) {
if (BIT_GET(data, i)) {
seed = i;
break;
}
}
}
Now for the output this will consume the most time
unsigned long bit_index = 0; // the current bit
int w = 8; // the width of a column
unsigned pc = 0; // prime, count, to assist in creating columns
for(int i=0;i<n;i++) {
unsigned long long int b = 1; // double width, so there is no overflow
// if a bit is still set, include that as a result
while(b < 0xFFFFFFFF) {
if (data[i]&b) {
printf("%8.u ", bit_index);
if(((pc++) % w) == 0)
putchar('\n'); // add a new row
}
bit_index++;
b<<=1; // multiply by 2, to check the next bit
}
}
clean up
delete [] data;