Full disclosure: this is for an online course.
The code calculates the distances between a starting node in a graph and all other nodes using the Bellman-Ford algorithm. The graph may contain negative cycles: in that case, the output should represent that distance with '-'. If there is no link between the starting node and another node it should '*'. Else, it should output the distance.
The code is working but I believe there is an overflow issue which I don't know how to solve. The constraints specify the following max values:
Nodes: 10^3;
Edges: 10^4;
Edge weights: 10^9
Testing for all logic-related corner cases led to no issues, everything was working correctly. The test this is failing is (most probably) related to overflow.
The code
void bfs(vector<vector<int> > &adj, queue<int> q, vector<bool> &shortest) {
int size = adj.size();
vector<bool> visited(size, false);
while (!q.empty()) {
int v = q.front();
if (visited[v]) {
q.pop();
} else {
q.pop();
for (int i = 0; i < adj[v].size(); i++) {
shortest[adj[v][i]] = true;
q.push(adj[v][i]);
}
}
visited[v] = true;
}
}
void shortest_paths(vector<vector<int> > &adj, vector<vector<int> > &cost, int s,
vector<double> &distance, vector<bool> &reachable, vector<bool> &shortest) {
int size = adj.size();
distance[s] = 0;
reachable[s] = true;
queue<int> negative_cycle;
// Set initial distances and get negative cycles
for (int i = 0; i <= size; i++) {
for (int j = 0; j < size; j++) {
for (int k = 0; k < adj[j].size(); k++) {
// Edge relaxation
if (distance[adj[j][k]] > distance[j] + cost[j][k]) {
reachable[adj[j][k]] = true;
if (i == size) {
// Store negative cycles
negative_cycle.push(adj[j][k]);
shortest[adj[j][k]] = true;
}
distance[adj[j][k]] = distance[j] + cost[j][k];
}
}
}
}
bfs(adj, negative_cycle, shortest);
}
and the main
int main() {
int n, m, s;
std::cin >> n >> m;
vector<vector<int> > adj(n, vector<int>());
vector<vector<int> > cost(n, vector<int>());
for (int i = 0; i < m; i++) {
double x, y, w;
std::cin >> x >> y >> w;
adj[x - 1].push_back(y - 1);
cost[x - 1].push_back(w);
}
std::cin >> s;
s--;
vector<double> distance(n, std::numeric_limits<double>::infinity());
vector<bool> reachable(n, false);
vector<bool> shortest(n, false);
shortest_paths(adj, cost, s, distance, reachable, shortest);
for (int i = 0; i < n; i++) {
if (!reachable[i]) {
std::cout << "*\n";
} else if (shortest[i]) {
std::cout << "-\n";
} else {
std::cout << distance[i] << "\n";
}
}
}
I'm using double and infinity since that is needed for the algorithm (you can read about it here). From the googling I've done, I get this shouldn't overflow since the max possible distance would be 10^4 * 10^9 = 10^13 which is still within double's span. I don't have much experience using infinity or doubles like this, and from what I've researched I couldn't trace the problem.
Is there an alternative to using double infinity (since long longdoesn't have it and it's max_size cannot be used in the context of the problem)? Can there be a double overflow in this case or other issues related (comparison failures, etc)?
Related
I'm running just a simple code, but I keep getting "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)"
Doing some debugging, I found that the value of edges[0].start somehow becomes -2147483644. I'm finding this behavior quite hard to explain and still trying to find where did I get it wrong but I don't even update any edges values! Anyways, whatever hints you can give me will be greatly valued. You will find the code bellow.
Thanks in advance!
Warm wishes
#include <stdio.h>
#include <climits>
#include "Utils.h"
struct edge {
int start;
int end;
int weight;
};
int main() {
int n = 4;
int m = 4;
edge edges[4] = {
{2,4,5},
{4,1,6},
{1,3,8},
{3,2,-3}
};
int v,e;
int distance[4];
// Step 1: initialize graph
for(v = 0; v < n; v++){
distance[v] = INT_MAX;
}
distance[0] = 0; //source
// Step 2: relax edges repeatedly
for(v = 0; v < n; v++){
for(e = 0; e < m; e++){
if(distance[edges[e].start] + edges[e].weight < distance[edges[e].end] ){ //relax
distance[edges[e].end] = distance[edges[e].start] + edges[e].weight;
}
}
}
// Step 3: check for negative-weight cycles
for(e = 0; e < m; e++) {
if (distance[edges[e].start] + edges[e].weight < distance[edges[e].end]) { //shouldn't be able to relax
std::cout << "Negative cycle detected, please declare war to Paraguay";
}
}
for(v = 0; v < n; v++){
std::cout << distance[v] << std::endl;
}
return 0;
}
Your 'n' and 'm' iterator variables are defined as 4, yet the 'edges' array has indexes between 0 and 3 inclusive. Your loop will try to access edges[4], resulting in an index out of range and undefined behaviour, which is the likely cause of your start value corruption.
You have defined distance variable with size of 4
int distance[4];
While the values of edge array are:
edge edges[4] = {
{2,4,5},
{4,1,6},
{1,3,8},
{3,2,-3}
};
You are using value of edge structure to access the cell of each distance array.
The value of edge ranges from -3 to 8 while the value of distance ranges from 0 to 3; This will cause the buffer overflow and will cause application to crash.
I'm actually don't know why, but this works for me:
#include <iostream>
struct edge {
int start;
int end;
int weight;
};
int main() {
int n = 4;
int m = 4;
const edge edges[4] = {
{2,4,5},
{4,1,6},
{1,3,8},
{3,2,-3}
}; /* <= for my surprise, I'm not get error with this
* for indexes of distance[something]
*/
int v,e;
int distance[4];
// Step 1: initialize graph
for(v = 0; v < n; v++){
distance[v] = 214748364; // <== with this get fixed
}
distance[0] = 0; //source
// Step 2: relax edges repeatedly
for(v = 0; v < n; v++){
for(e = 0; e < m; e++){
if(distance[edges[e].start] + edges[e].weight < distance[edges[e].end] ){ //relax
distance[edges[e].end] = distance[edges[e].start] + edges[e].weight;
}
}
}
// Step 3: check for negative-weight cycles
for(e = 0; e < m; e++) {
if (distance[edges[e].start] + edges[e].weight < distance[edges[e].end]) { //shouldn't be able to relax
std::cout << "Negative cycle detected, please declare war to Paraguay";
}
}
for(v = 0; v < n; v++){
std::cout << distance[v] << std::endl;
}
return 0;
}
Instead of use distance[v] = INT_MAX; simply use distance[v] = 214748364; or something not so close of INT_MAX and I get this output:
0
8
13
16
Press <RETURN> to close this window...
What i'm trying to do is implement a simple selection sort algorithm that uses the function minButGreaterThan to find the next smallest number in the array. My problem is if the array has a duplicate number, it gets passed over and left at the end. I've tried changing the controlling if statements to accommodate for this but nothing seems to work. Any advice?
double GradeBook::minButGreaterThan(double x) // - NEEDS TESTING
{
double minButGreaterThan = -1;
for (int i = 0; i < classSize; i++)
{
if (grades[i] > x)
{
minButGreaterThan = grades[i];
break;
}
}
for (int i = 0; i < classSize; i++)
{
if (grades[i] > x && grades[i] <= minButGreaterThan)
minButGreaterThan = grades[i];
}
return minButGreaterThan;
}
void GradeBook::selectionSort() //ascending order -- *DOES NOT WORK WITH DUPLICATE SCORES* - RETEST
{
double min = absoluteMin();
for (int i = 0; i < classSize; i++)
{
if (grades[i] == min)
{
double temp = grades[0];
grades[0] = grades[i];
grades[i] = temp;
break;
}
}
for (int i = 0; i < classSize-1; i++)
{
double next = minButGreaterThan(grades[i]);
for (int n = 1; n <= classSize; n++)
if (grades[n] == next)
{
double temp = grades[n];
grades[n] = grades[i+1];
grades[i+1] = temp;
}
}
}
Should work with duplicates, a selection sort just takes the minimum and moves it to the left, to the "sorted" portion of the array.
This is my implementation:
#include <algorithm>
#include <vector>
using std::swap;
using std::vector;
using std::min_element;
void selectionSort(vector<int> &v) {
for (unsigned int i = 0; i < v.size() - 1; i++) {
auto minElement = min_element(v.begin() + i, v.end());
auto minIndex = minElement - v.begin();
swap(v[i], v[minIndex]);
}
}
You might need to modify it to work with floats. Now, a double floating precision grade (double) seems too much. I think a regular float is OK.
I know how to generate all n-digit number in the traditional number way,
for(long long number = pow(10, n-1); number < pow(10, n); number++) {
cout << number << endl;
}
for example,
for n = 5, it will generate 10000 to 99999;
However, since I will have to evaluate each number's digits, it is much convenient to construct the numbers in a digit array format in the first place.
for example, following code generate all 5-digit number in an array way:
for(int i = 1; i < 9; i++)
for(int j = 0; j < 9; j++)
for(int k = 0; k < 9; k++)
for(int l = 0; l < 9; l++)
for(int m = 0; m < 9; m++) {
//executed 9 * 10^4 = 90000 times
//construct my array instance with i, j, k, l, m
cout << i << j << k << l << m << endl;
}
Now the problem is: n is unknown. (for example, it could be 2, 3, 4, 5, 6..., 10)
Then how can I generate n-digit-array based on a number n?
For example, I want a piece of code like follows (any better ways than this one is highly appreciated):
for(int x = 0; x < n; x++) {
//each x is a layer of the loop ?!
.....
}
There is no reason to limit ourselves to the range 0 - 9 for each digit of the number.
For each numerical place, we'll represent a range:
std::pair<int,int> range;
Each loop in your example is iterating from the beginning of the range to the end of the range.
All the loops together are really just a series of ranges; each nested loop being responsible for the next digit of your generated number.
We can represent that, in the following way:
std::vector<std::pair<int, int>> ranges;
If you think about how nested for loops work, you can emulate the same functionality over the vector using two pointers. I've done that and wrapped the functionality into a class:
//header
class Range_Combinator {
public:
Range_Combinator(std::vector<std::pair<int, int>> const &ranges_in);
std::vector<int> Next();
std::vector<int> Current();
bool Done();
private:
bool Adjust();
void Reset_From_Current_Back(int from);
std::vector<std::pair<int, int>> ranges;
int current;
int last;
bool all_exausted;
std::vector<int> current_vals;
};
//source
Range_Combinator::Range_Combinator(
std::vector<std::pair<int, int>> const &ranges_in) {
ranges = ranges_in;
last = ranges.size() - 1;
current = last;
all_exausted = false;
for (auto it : ranges) {
current_vals.push_back(it.first);
}
}
std::vector<int> Range_Combinator::Next() {
all_exausted = Adjust();
return current_vals;
}
std::vector<int> Range_Combinator::Current() { return current_vals; }
bool Range_Combinator::Done() { return all_exausted; }
bool Range_Combinator::Adjust() {
if (current_vals[current] < ranges[current].second) {
current_vals[current]++;
} else {
while (current_vals[current] == ranges[current].second) {
current--;
}
if (current < 0) {
return true;
}
Reset_From_Current_Back(current + 1);
current_vals[current]++;
current = last;
}
return false;
}
void Range_Combinator::Reset_From_Current_Back(int from) {
for (int i = from; i <= last; ++i) {
current_vals[i] = ranges[i].first;
}
}
This is how you would use it:
//create range combinator
std::vector<std::pair<int,int>> ranges{{1,2},{3,4}};
Range_Combinator r(ranges);
//print each number
auto number = r.Current();
while (!r.Done()){
for (auto it: number) std::cout << it; std::cout << '\n';
number = r.Next();
}
//prints: 13
// 14
// 23
// 24
I don't know why you need that but you can try this:
size_t n = ; //whatever value
unsigned char* x = new unsigned char[n]();
x[0] = 1; //make it n-digit 10000...000
do
{
//process digits here
++x[n - 1];
for (size_t i = n; i > 1; --i)
{
if (x[i - 1] == 10)
{
x[i - 1] = 0;
++x[i - 2];
}
}
} while (x[0] < 10);
delete [] x;
You can even process not decimal numbers, just replace hard-coded 10 into appropriate number.
I suppose I could just write out the whole thing for you, but that would be no fun. Instead, I'll just outline the basic approach, and you can finish the answer yourself by filling in the blanks.
Consider an n-digit long number being represented this way:
struct digit {
struct digit *next;
int n; /* Digit 0-9 */
};
A single number represented, in this manner, can be printed out this way:
void print_digit(struct digit *p)
{
while (p)
{
std::cout << p->n;
p=p->next;
}
std::cout << std::endl;
}
Now, let's create a recursive loop, that iterates over all possible n-digit numbers:
void iterate(int ndigits)
{
for (int i=0; i<10; ++i)
{
if (ndigits > 1)
{
iterate(ndigits-1);
}
else
{ // This is the last digit
// Here be dragons
}
}
}
After a bit of thinking, you can see that if, for example, you call iterate(4), then when the "hear be dragons" part gets executed, this will be inside a four-deep nested iteration stack. There will be four level-deep for loops, nested within each other. And, with iterate(6), there will be six of them, and so on.
Now, consider the fact that the struct digit-based representation of n-digit numbers is also a stack, of sorts.
Therefore, the homework assignment here would be to use this recursive iteration to dynamically construct this linked list, on the stack, with the "here be dragons" part simply invoking print_digit() in order to print each number.
Hint: iterate() will need to have a few more parameters, that it will use appropriately, with a certain preset value for them, on the initial call to iterate().
A simple way without thinking of efficiency:
#include <cstdio>
int main(void) {
int n = 3; // the number of digits
long long start = 1;
int *array = new int[n];
for (int i = 1; i < n; i++) start *= 10;
for(long long x = start; x < start * 10; x++) { // not all 10-digit number will fit in 32-bit integer
// get each digits in decimal, lowest digit in array[0]
for (int i = 0, shift = 1; i < n; i++, shift *= 10) array[i] = (int)((x / shift) % 10);
// do some work with it (print it here)
for (int i = n - 1; i >= 0; i--) printf("%d", array[i]);
putchar('\n');
}
delete[] array;
return 0;
}
I wanted to count the number of groups in an undirected graphs in c++.I was trying using bfs but was unsuccessful.I have been given a range of numbers [L,R] (or think of these ranges as number of vertices) and i have to find the number of groups.How do i do this?
Like if i have (Input):
1 3
2 5
6 9
Output:
2
As there are 2 groups.
My code:
bool visited[MAX];
vector<int> v[MAX];
int solve(int x)
{
queue<int> q;int ans=0;
q.push(x);
if(v[x].empty())
{
ans++;
}
while(!q.empty())
{
int curr = q.front();
visited[curr] = true;
q.pop();
for(int i = 0; i < v[curr].size(); i ++)
{
if(!visited[v[curr][i]])
{
q.push(v[curr][i]);
visited[v[curr][i]] = true;
}
}
if(v[curr].empty()) ans++;
}
return ans;
}
int main()
{
int t;scanf("%d",&t);
while(t--)
{
int l,r,n,ans=0,min_,max_=0;
scanf("%d",&n);
for(int i = 0; i < n; i ++)
visited[i] = false;
for(int j=0;j<n;j++)
{
scanf("%d",&l);scanf("%d",&r);
for(int i=l;i<r;i++)
{
v[i].push_back(i+1);
min_ = min(min_,i);
max_ = max(max_,i+1);
}
}
printf("%d\n",solve(min_));
}
return 0;
}
Let's take a look at how many edges are created in the worst case. It is N * (MAX_R - MIN_L), which is 10^5 * 2000 under given constraints. You program runs out of memory and gets runtime error. A more efficient algorithm is required. Here is a simple solution that uses only O(MAX_R) memory and O(N + MAX_R) time.
vector<int> start(MAX_R + 1);
vector<int> end(MAX_R + 1);
int n;
cin >> n;
for (int i = 0; i < n; i++) {
int low;
int high;
cin >> low >> high;
start[low]++;
end[high]++;
}
int res = 0;
int sum = 0;
for (int pos = 0; pos <= MAX_R; pos++) {
if (sum == 0 && start[pos] > 0)
res++;
sum += start[pos] - end[pos];
}
cout << res << endl;
There is no need for bfs or any other graph algorithms in this problem.
You could fix your original solution by avoiding multiple edges in the graph(there is no need to create an edge from i to i + 1 if it already exists, but I am not sure if your original solution is correct).
Looks like you should start by changing to vector<pair<int,int>> v;. Then to populate v you should use:
scanf("%d", &l);scanf("%d", &r);
v.push_back(make_pair(l, r);
Then your function should become something like:
int solve(){
vector<pair<int, int>> results;
for(auto& vIndex : v){
auto resultIndex = find_if(results.begin(), results.end(), [vIndex](const pair<int, int>& i){return vIndex.first >= i.first && vIndex.first <= i.second || vIndex.second >= i.first && vIndex.second <= i.second;});
if(resultIndex == results.end()){
results.push_back(vIndex);
}else{
resultIndex->first = min(vIndex.first, resultIndex->first);
resultIndex->second = max(vIndex.second, resultIndex->second);
}
}
return results.size();
}
You can see this in action here: http://ideone.com/MDQBOr Just hard code your desired inputs into v.
I am currently reading "Programming: Principles and Practice Using C++", in Chapter 4 there is an exercise in which:
I need to make a program to calculate prime numbers between 1 and 100 using the Sieve of Eratosthenes algorithm.
This is the program I came up with:
#include <vector>
#include <iostream>
using namespace std;
//finds prime numbers using Sieve of Eratosthenes algorithm
vector<int> calc_primes(const int max);
int main()
{
const int max = 100;
vector<int> primes = calc_primes(max);
for(int i = 0; i < primes.size(); i++)
{
if(primes[i] != 0)
cout<<primes[i]<<endl;
}
return 0;
}
vector<int> calc_primes(const int max)
{
vector<int> primes;
for(int i = 2; i < max; i++)
{
primes.push_back(i);
}
for(int i = 0; i < primes.size(); i++)
{
if(!(primes[i] % 2) && primes[i] != 2)
primes[i] = 0;
else if(!(primes[i] % 3) && primes[i] != 3)
primes[i]= 0;
else if(!(primes[i] % 5) && primes[i] != 5)
primes[i]= 0;
else if(!(primes[i] % 7) && primes[i] != 7)
primes[i]= 0;
}
return primes;
}
Not the best or fastest, but I am still early in the book and don't know much about C++.
Now the problem, until max is not bigger than 500 all the values print on the console, if max > 500 not everything gets printed.
Am I doing something wrong?
P.S.: Also any constructive criticism would be greatly appreciated.
I have no idea why you're not getting all the output, as it looks like you should get everything. What output are you missing?
The sieve is implemented wrongly. Something like
vector<int> sieve;
vector<int> primes;
for (int i = 1; i < max + 1; ++i)
sieve.push_back(i); // you'll learn more efficient ways to handle this later
sieve[0]=0;
for (int i = 2; i < max + 1; ++i) { // there are lots of brace styles, this is mine
if (sieve[i-1] != 0) {
primes.push_back(sieve[i-1]);
for (int j = 2 * sieve[i-1]; j < max + 1; j += sieve[i-1]) {
sieve[j-1] = 0;
}
}
}
would implement the sieve. (Code above written off the top of my head; not guaranteed to work or even compile. I don't think it's got anything not covered by the end of chapter 4.)
Return primes as usual, and print out the entire contents.
Think of the sieve as a set.
Go through the set in order. For each value in thesive remove all numbers that are divisable by it.
#include <set>
#include <algorithm>
#include <iterator>
#include <iostream>
typedef std::set<int> Sieve;
int main()
{
static int const max = 100;
Sieve sieve;
for(int loop=2;loop < max;++loop)
{
sieve.insert(loop);
}
// A set is ordered.
// So going from beginning to end will give all the values in order.
for(Sieve::iterator loop = sieve.begin();loop != sieve.end();++loop)
{
// prime is the next item in the set
// It has not been deleted so it must be prime.
int prime = *loop;
// deleter will iterate over all the items from
// here to the end of the sieve and remove any
// that are divisable be this prime.
Sieve::iterator deleter = loop;
++deleter;
while(deleter != sieve.end())
{
if (((*deleter) % prime) == 0)
{
// If it is exactly divasable then it is not a prime
// So delete it from the sieve. Note the use of post
// increment here. This increments deleter but returns
// the old value to be used in the erase method.
sieve.erase(deleter++);
}
else
{
// Otherwise just increment the deleter.
++deleter;
}
}
}
// This copies all the values left in the sieve to the output.
// i.e. It prints all the primes.
std::copy(sieve.begin(),sieve.end(),std::ostream_iterator<int>(std::cout,"\n"));
}
From Algorithms and Data Structures:
void runEratosthenesSieve(int upperBound) {
int upperBoundSquareRoot = (int)sqrt((double)upperBound);
bool *isComposite = new bool[upperBound + 1];
memset(isComposite, 0, sizeof(bool) * (upperBound + 1));
for (int m = 2; m <= upperBoundSquareRoot; m++) {
if (!isComposite[m]) {
cout << m << " ";
for (int k = m * m; k <= upperBound; k += m)
isComposite[k] = true;
}
}
for (int m = upperBoundSquareRoot; m <= upperBound; m++)
if (!isComposite[m])
cout << m << " ";
delete [] isComposite;
}
Interestingly, nobody seems to have answered your question about the output problem. I don't see anything in the code that should effect the output depending on the value of max.
For what it's worth, on my Mac, I get all the output. It's wrong of course, since the algorithm isn't correct, but I do get all the output. You don't mention what platform you're running on, which might be useful if you continue to have output problems.
Here's a version of your code, minimally modified to follow the actual Sieve algorithm.
#include <vector>
#include <iostream>
using namespace std;
//finds prime numbers using Sieve of Eratosthenes algorithm
vector<int> calc_primes(const int max);
int main()
{
const int max = 100;
vector<int> primes = calc_primes(max);
for(int i = 0; i < primes.size(); i++)
{
if(primes[i] != 0)
cout<<primes[i]<<endl;
}
return 0;
}
vector<int> calc_primes(const int max)
{
vector<int> primes;
// fill vector with candidates
for(int i = 2; i < max; i++)
{
primes.push_back(i);
}
// for each value in the vector...
for(int i = 0; i < primes.size(); i++)
{
//get the value
int v = primes[i];
if (v!=0) {
//remove all multiples of the value
int x = i+v;
while(x < primes.size()) {
primes[x]=0;
x = x+v;
}
}
}
return primes;
}
In the code fragment below, the numbers are filtered before they are inserted into the vector. The divisors come from the vector.
I'm also passing the vector by reference. This means that the huge vector won't be copied from the function to the caller. (Large chunks of memory take long times to copy)
vector<unsigned int> primes;
void calc_primes(vector<unsigned int>& primes, const unsigned int MAX)
{
// If MAX is less than 2, return an empty vector
// because 2 is the first prime and can't be placed in the vector.
if (MAX < 2)
{
return;
}
// 2 is the initial and unusual prime, so enter it without calculations.
primes.push_back(2);
for (unsigned int number = 3; number < MAX; number += 2)
{
bool is_prime = true;
for (unsigned int index = 0; index < primes.size(); ++index)
{
if ((number % primes[k]) == 0)
{
is_prime = false;
break;
}
}
if (is_prime)
{
primes.push_back(number);
}
}
}
This not the most efficient algorithm, but it follows the Sieve algorithm.
below is my version which basically uses a bit vector of bool and then goes through the odd numbers and a fast add to find multiples to set to false. In the end a vector is constructed and returned to the client of the prime values.
std::vector<int> getSieveOfEratosthenes ( int max )
{
std::vector<bool> primes(max, true);
int sz = primes.size();
for ( int i = 3; i < sz ; i+=2 )
if ( primes[i] )
for ( int j = i * i; j < sz; j+=i)
primes[j] = false;
std::vector<int> ret;
ret.reserve(primes.size());
ret.push_back(2);
for ( int i = 3; i < sz; i+=2 )
if ( primes[i] )
ret.push_back(i);
return ret;
}
Here is a concise, well explained implementation using bool type:
#include <iostream>
#include <cmath>
void find_primes(bool[], unsigned int);
void print_primes(bool [], unsigned int);
//=========================================================================
int main()
{
const unsigned int max = 100;
bool sieve[max];
find_primes(sieve, max);
print_primes(sieve, max);
}
//=========================================================================
/*
Function: find_primes()
Use: find_primes(bool_array, size_of_array);
It marks all the prime numbers till the
number: size_of_array, in the form of the
indexes of the array with value: true.
It implemenets the Sieve of Eratosthenes,
consisted of:
a loop through the first "sqrt(size_of_array)"
numbers starting from the first prime (2).
a loop through all the indexes < size_of_array,
marking the ones satisfying the relation i^2 + n * i
as false, i.e. composite numbers, where i - known prime
number starting from 2.
*/
void find_primes(bool sieve[], unsigned int size)
{
// by definition 0 and 1 are not prime numbers
sieve[0] = false;
sieve[1] = false;
// all numbers <= max are potential candidates for primes
for (unsigned int i = 2; i <= size; ++i)
{
sieve[i] = true;
}
// loop through the first prime numbers < sqrt(max) (suggested by the algorithm)
unsigned int first_prime = 2;
for (unsigned int i = first_prime; i <= std::sqrt(double(size)); ++i)
{
// find multiples of primes till < max
if (sieve[i] = true)
{
// mark as composite: i^2 + n * i
for (unsigned int j = i * i; j <= size; j += i)
{
sieve[j] = false;
}
}
}
}
/*
Function: print_primes()
Use: print_primes(bool_array, size_of_array);
It prints all the prime numbers,
i.e. the indexes with value: true.
*/
void print_primes(bool sieve[], unsigned int size)
{
// all the indexes of the array marked as true are primes
for (unsigned int i = 0; i <= size; ++i)
{
if (sieve[i] == true)
{
std::cout << i <<" ";
}
}
}
covering the array case. A std::vector implementation will include minor changes such as reducing the functions to one parameter, through which the vector is passed by reference and the loops will use the vector size() member function instead of the reduced parameter.
Here is a more efficient version for Sieve of Eratosthenes algorithm that I implemented.
#include <iostream>
#include <cmath>
#include <set>
using namespace std;
void sieve(int n){
set<int> primes;
primes.insert(2);
for(int i=3; i<=n ; i+=2){
primes.insert(i);
}
int p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
int maxRoot = sqrt(*(primes.rbegin()));
while(primes.size()>0){
if(p>maxRoot){
while(primes.size()>0){
p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
}
break;
}
int i=p*p;
int temp = (*(primes.rbegin()));
while(i<=temp){
primes.erase(i);
i+=p;
i+=p;
}
p=*primes.begin();
cout<<p<<"\n";
primes.erase(p);
}
}
int main(){
int n;
n = 1000000;
sieve(n);
return 0;
}
Here's my implementation not sure if 100% correct though :
http://pastebin.com/M2R2J72d
#include<iostream>
#include <stdlib.h>
using namespace std;
void listPrimes(int x);
int main() {
listPrimes(5000);
}
void listPrimes(int x) {
bool *not_prime = new bool[x];
unsigned j = 0, i = 0;
for (i = 0; i <= x; i++) {
if (i < 2) {
not_prime[i] = true;
} else if (i % 2 == 0 && i != 2) {
not_prime[i] = true;
}
}
while (j <= x) {
for (i = j; i <= x; i++) {
if (!not_prime[i]) {
j = i;
break;
}
}
for (i = (j * 2); i <= x; i += j) {
not_prime[i] = true;
}
j++;
}
for ( i = 0; i <= x; i++) {
if (!not_prime[i])
cout << i << ' ';
}
return;
}
I am following the same book now. I have come up with the following implementation of the algorithm.
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<cmath>
using namespace std;
inline void keep_window_open() { char ch; cin>>ch; }
int main ()
{
int max_no = 100;
vector <int> numbers (max_no - 1);
iota(numbers.begin(), numbers.end(), 2);
for (unsigned int ind = 0; ind < numbers.size(); ++ind)
{
for (unsigned int index = ind+1; index < numbers.size(); ++index)
{
if (numbers[index] % numbers[ind] == 0)
{
numbers.erase(numbers.begin() + index);
}
}
}
cout << "The primes are\n";
for (int primes: numbers)
{
cout << primes << '\n';
}
}
Here is my version:
#include "std_lib_facilities.h"
//helper function:check an int prime, x assumed positive.
bool check_prime(int x) {
bool check_result = true;
for (int i = 2; i < x; ++i){
if (x%i == 0){
check_result = false;
break;
}
}
return check_result;
}
//helper function:return the largest prime smaller than n(>=2).
int near_prime(int n) {
for (int i = n; i > 0; --i) {
if (check_prime(i)) { return i; break; }
}
}
vector<int> sieve_primes(int max_limit) {
vector<int> num;
vector<int> primes;
int stop = near_prime(max_limit);
for (int i = 2; i < max_limit+1; ++i) { num.push_back(i); }
int step = 2;
primes.push_back(2);
//stop when finding the last prime
while (step!=stop){
for (int i = step; i < max_limit+1; i+=step) {num[i-2] = 0; }
//the multiples set to 0, the first none zero element is a prime also step
for (int j = step; j < max_limit+1; ++j) {
if (num[j-2] != 0) { step = num[j-2]; break; }
}
primes.push_back(step);
}
return primes;
}
int main() {
int max_limit = 1000000;
vector<int> primes = sieve_primes(max_limit);
for (int i = 0; i < primes.size(); ++i) {
cout << primes[i] << ',';
}
}
Here is a classic method for doing this,
int main()
{
int max = 500;
vector<int> array(max); // vector of max numbers, initialized to default value 0
for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
{
// initialize j as a composite number; increment in consecutive composite numbers
for (int j = i * i; j < array.size(); j +=i)
array[j] = 1; // assign j to array[index] with value 1
}
for (int i = 2; i < array.size(); ++ i) // loop for rang of numbers from 2 to max
if (array[i] == 0) // array[index] with value 0 is a prime number
cout << i << '\n'; // get array[index] with value 0
return 0;
}
I think im late to this party but im reading the same book as you, this is the solution in came up with! Feel free to make suggestions (you or any!), for what im seeing here a couple of us extracted the operation to know if a number is multiple of another to a function.
#include "../../std_lib_facilities.h"
bool numIsMultipleOf(int n, int m) {
return n%m == 0;
}
int main() {
vector<int> rawCollection = {};
vector<int> numsToCheck = {2,3,5,7};
// Prepare raw collection
for (int i=2;i<=100;++i) {
rawCollection.push_back(i);
}
// Check multiples
for (int m: numsToCheck) {
vector<int> _temp = {};
for (int n: rawCollection) {
if (!numIsMultipleOf(n,m)||n==m) _temp.push_back(n);
}
rawCollection = _temp;
}
for (int p: rawCollection) {
cout<<"N("<<p<<")"<<" is prime.\n";
}
return 0;
}
Try this code it will be useful to you by using java question bank
import java.io.*;
class Sieve
{
public static void main(String[] args) throws IOException
{
int n = 0, primeCounter = 0;
double sqrt = 0;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println(“Enter the n value : ”);
n = Integer.parseInt(br.readLine());
sqrt = Math.sqrt(n);
boolean[] prime = new boolean[n];
System.out.println(“\n\nThe primes upto ” + n + ” are : ”);
for (int i = 2; i<n; i++)
{
prime[i] = true;
}
for (int i = 2; i <= sqrt; i++)
{
for (int j = i * 2; j<n; j += i)
{
prime[j] = false;
}
}
for (int i = 0; i<prime.length; i++)
{
if (prime[i])
{
primeCounter++;
System.out.print(i + ” “);
}
}
prime = new boolean[0];
}
}