calculate the biggest sum of consecutive Elements ( in a list) - c++

I'm trying to calculate the biggest sum of consecutive elements of a vector<int>, but I don't really know how to do:
I started to code that:
#include <iostream>
#include <vector>
using namespace std;
void calcule_somme(vector<int> tab);
void calcule_somme(vector<int> tab) {
int somme_partielle(0);
vector<int> element_les_plusgrand;
for(size_t i(0);tab.size();++i) {
for(size_t j(i+1);tab.size();++i) {
element_les_plusgrand.pushback(tab[i]);
if (tab[i]+tab[j]>compteur) {
element_les_plusgrand.push_back(tab[j]);
compteur = tab[i]+tab[j];
}
}
int main() {
return 0;
}
The function has to return: the biggest sum of consecutive element is "4,5,78" which is equal to 87.

#include <iostream>
#include <vector>
using namespace std;
int sum(const vector<int>& tab) {
int sum = 0;
for (size_t i = 0; i < tab.size(); i++) {
sum += tab[i];
}
return sum;
}
vector<int> calculate_sume(const vector<int>& tab) {
vector<int> ret, current;
int previous = -32767;
for (size_t i = 0; i < tab.size(); i++) {
if ((tab[i] > previous) == false) {
if (current.size() >= ret.size() && sum(current) > sum(ret))
ret = current;
current.clear();
}
current.push_back(tab[i]);
previous = tab[i];
}
for(size_t w(0);w<ret.size();++w) {
cout << ret[w]<< " ";
}
return ret;
}
int main() {
vector<int> tab ={-4,5,6,-9,24,-35,4,5,78};
sum(tab);
calculate_sume(tab);
return 0;
}
Tell me -4 5 6

First off, you'll need to keep track of two vectors, one to hold the largest sequence of characters and one to hold the values that currently being calculated.
From there, you just need to iterate through the elements in the source vector keeping track of the previous and current value in the vector.
If the current value is greater than the previous value, you push the current value into the current vector and then assign the previous value to the current value.
If it's less than (or I'm assuming equal), the consecutive sequence is completed and you should start with the next sequence. This means that you need to do the following:
Determine if the current vector's size is greater than or equal the largest vector's size and the sum of the current vector is greater than the sum of the largest. If it is, assign largest = current;
Clear the current list
Assign previous to the current int value.
Here is how I would write it:
int sum(const vector<int>& tab) {
int sum = 0;
for (size_t i = 0; i < tab.size(); i++) {
sum += tab[i];
}
return sum;
}
vector<int> calculate_some(const vector<int>& tab) {
vector<int> ret, current;
int previous = tab[0];
current.push_back(previous);
for (size_t i = 1; i < tab.size(); i++) {
current.push_back(tab[i]);
if (tab[i] <= previous || i == (tab.size() - 1)) {
if (current.size() >= ret.size() && sum(current) > sum(ret))
ret = current;
current.clear();
}
previous = tab[i];
}
return ret;
}
And here is how I am calling it:
int main() {
vector<int> tab = { -4,5,6,-9,24,-35,4,5,78 };
vector<int> results = calculate_some(tab);
for (size_t w(0); w<results.size(); ++w) {
cout << results[w] << " ";
}
system("pause");
return 0;
}

pseudocode:
Algorithm Biggest_Consecutive_Sum
Input: Vector v
Output: Biggest_Sum
begin
index = 0, Biggest_Sum = 0
while(index < v.size()){
Sum = 0
while (Sum + V[index] > Sum){
Sum = Sum + V[index]
index = index + 1
}
if(Sum > Biggest_Sum) Biggest_Sum = Sum
index = index + 1
}
return Biggest_Sum
end

Related

Sum of the two lowest positive numbers in a vector

I made a function sumOfTwoSmallestNumbers() that takes an integer vector (containing only positive values) and it returns the sum of the two lowest positive numbers stored in that vector. Unfortunately, my function fails for a few test cases (I do not have access to the inputs of those test cases). Please help me find the error in my code.
NOTE: Vector always consists of a minimum of 4 positive values
#include <iostream>
#include <vector>
using namespace std;
long sumOfTwoSmallestNumbers (vector<int> numbers)
{
long int sum = 0;
long int min1 = numbers[0];
int position;
for (unsigned long int i = 0; i < numbers.size(); i++){
if (numbers[i] < min1){
min1 = numbers[i];
position = i;
}
}
numbers.erase(numbers.begin() + position - 1);
long int min2 = numbers[0];
for (unsigned long int i = 0; i < numbers.size(); i++){
if (numbers[i] < min2){
min2 = numbers[i];
}
}
sum = min1 + min2;
return sum;
}
Logic:
I have tried to first find the smallest value and store it in a variable and then remove that value from the vector. After that, I again searched for the smallest value in the vector and stored it in a variable. In end, I have added the two values and returned the sum.
Your code has a couple of issues:
If the smallest number in the vector is the first, position will be uninitialized and cause UB (Undefined Behavior).
If you'll initiazlie position to 0 as required, then again if the smallest number in the vector is the first, this line numbers.erase(numbers.begin() + position - 1) will attempt to use an iterator to before numbers.begin(). This is invalid.
My solution below only keeps track of smallest and secondSmallest without having to modify the vector at all (and thus I can pass it by const&). It also requires only one traverse of the vector (and the complexity is O(n)).
#include <iostream>
#include <vector>
#include <assert.h>
long sumOfTwoSmallestNumbers(std::vector<int> const & numbers)
{
assert(numbers.size() >= 4); // The OP specified that in the question.
int smallest = (numbers[0] < numbers[1]) ? numbers[0] : numbers[1];
int secondSmallest = (numbers[0] < numbers[1]) ? numbers[1] : numbers[0];
for (size_t i = 2; i < numbers.size(); ++i)
{
if (numbers[i] < smallest)
{
// Need to update both:
secondSmallest = smallest;
smallest = numbers[i];
}
else if (numbers[i] < secondSmallest)
{
// Need to update only second:
secondSmallest = numbers[i];
}
}
return (smallest + secondSmallest);
}
int main()
{
std::vector<int> v = { 1,4,7,2 };
auto s = sumOfTwoSmallestNumbers(v);
std::cout << "sumOfTwoSmallestNumbers: " << s << std::endl;
return 0;
}
Output:
sumOfTwoSmallestNumbers: 3
A side note: it's better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
What do you think of this:
// Simple function that will swap smallest with next_smallest
// if smallest > next_smallest. Returns true if a swap happened
bool TwoItemSort(int& smallest, int& next_smallest)
{
if (next_smallest < smallest)
{
int tmp = smallest;
smallest = next_smallest;
next_smallest = tmp;
return true;
}
return false;
}
long sumOfTwoSmallestNumbers(const vector<int>& numbers)
{
if (numbers.size() < 2)
{
return 0;
}
int smallest = numbers[0];
int nextsmallest = numbers[1];
TwoItemSort(smallest, nextsmallest);
for (size_t i = 2; i < numbers.size(); i++)
{
int value = numbers[i];
if (TwoItemSort(nextsmallest, value))
{
TwoItemSort(smallest, nextsmallest);
}
}
return smallest + nextsmallest;
}
um, this is a two-liner...
std::sort(vec.begin(),vec.end());
auto sum = vec.at(0) + vec.at(1);
Hope this helps
Caveat: it does not skip negative numbers, but that has been left out as a learning exercise for the OP.
#include <bits/stdc++.h>
using namespace std;
int sumOfSmallestPositive(vector<int> arr);
int main()
{
vector<int> arr{-8,-24,14,-56,-1,5,87,12,-10,11};
cout<<sumOfSmallestPositive(arr);
return 0;
}
int sumOfSmallestPositive(vector<int> arr)
{
sort(arr.begin(),arr.end());
pair<int,int> p;
for(int i=0;i<arr.size();i++)
{
if(arr[i]>0)
{
p.first=arr[i];
p.second=0;
if(i+1<=arr.size()-1)
p.second=arr[i+1];
break;
}
}
return p.first +p.second; //return 5+11=16
}

Removing odd numbers from an array

I am trying to remove odd numbers from an array, but I'm not allowed to create a new array to store the new values.
So, if I have arr[1,2,3,4,5,6,7,8,9]
then I need it to be arr[2,4,6,8] so that arr[0] will be 2 and not 1.
I can't seem to be able to drop the even numbers without creating a new array to store the values and then feed it back into the original array with the new values.
I have tried to make arr[i] = 0 if its an odd number but then I wasn't able to drop the 0 and replace it with the next even number.
So far, I have this:
void removeOdd(int arr[], int& arrSize){
int i, j = 0;
int temp;
int newArrSize;
for(i = 0, newArrSize = arrSize; i < arrSize; i++){
if(arr[i] % 2 != 0){
arr[i] = 0;
}
}
arrSize = newArrSize;
}
// Moves all even numbers into the beginning of the array in their original order
int removeOdd(int arr[], int arrSize) {
int curr = 0; // keep track of current position to insert next even number into
for (int i = 0; i < arrSize; ++i) {
if (arr[i] % 2 == 0) {
arr[curr++] = arr[i];
}
}
return curr;
}
int main() {
int arr[10] = { 0,1,2,3,4,5,6,7,8,9 };
int newSize = removeOdd(arr, 10);
for (int i = 0; i < newSize; ++i) {
std::cout << arr[i] << " ";
}
}
0 2 4 6 8
You might want to use std::vector:
void removeOdd(std::vector<int>& arr) {
int curr = 0;
for (int i = 0; i < (int)arr.size(); ++i) {
if (arr[i] % 2 == 0) {
arr[curr++] = arr[i];
}
}
arr.resize(curr);
}
int main() {
std::vector<int> arr = { 0,1,2,3,4,5,6,7,8,9 };
removeOdd(arr);
for (int number : arr) {
std::cout << number << " ";
}
}
Normally (unless this is homework of some sort), you should use the algorithms in the <algorithm> header.
Using std::remove_if with std::vector's erase member function, you will accomplish exactly what you want with less code:
std::vector<int> vec{ 1,2,3,4,5,6,7,8,10 };
vec.erase(std::remove_if(std::begin(vec), std::end(vec), [](auto const& i) {
return i % 2 != 0;
}), std::end(vec));
Demo

How can I sort array elements by number of divisors?

My problem is that I hit an obstacle while I was solving some exercises.
The source of the problem is that I have to write a program which sort descending an array by the number of each element's divisors, but when two element has the same number of divisors it should sort ascending those values.
My code so far:
#include <iostream>
#include <fstream>
using namespace std;
int cntDiv(int n) //get number of divisors
{
int lim = n;
int c = 0;
if(n == 1)
return 1;
for(int i = 1; i < lim; i++)
{
if(n % i == 0)
{
lim = n / i;
if(lim != i)
c++;
c++;
}
}
return c;
}
int main()
{
ifstream fin("in.txt");
int n, i, j;
fin >> n;
int v[n];
for(i = 0; i < n; i++)
fin >> v[i];
int div[n];
for(i = 0; i < n; i++)
div[i] = cntDiv(v[i]);
for(i = 0; i < n - 1; i++)
{
for(j = i + 1; j < n; j++)
{
if(div[i] < div[j] && div[i] != div[j]) //if the number of divisors are different
{
int t = v[i];
v[i] = v[j];
v[j] = t;
t = div[i];
div[i] = div[j];
div[j] = t;
}
if(div[i] == div[j] && v[i] > v[j]) //if the number of divisors are the same
{
int t = v[i];
v[i] = v[j];
v[j] = t;
}
}
}
for(i = 0; i < n; i++)
{
cout << v[i] << " ";
}
return 0;
}
In.txt:
5
12 20 4 100 13
Output:
100 12 20 4 13
Although it works fine with this one and many other. For bigger inputs it exceeds the time limit which is 0.1s. Any advice how should I rewrite the sorting? (I wrote bubble sort because I could not implement sorting array by property via quicksort)
Use an array of structures. The structure would contain the original value and a container of divisors:
struct Number_Attributes
{
int number;
std::list<int> divisors;
};
You can then write a custom comparator function and pass to std::sort:
bool Order_By_Divisors(const Number_Attributes& a,
const Number_Attributes& b)
{
return a.divisors.size() < b.divisors.size();
}
The sorting then becomes:
#define ARRAY_CAPACITY (20U)
Number_Attributes the_array[ARRAY_CAPACITY];
//...
std::sort(&array[0], &array[ARRAY_CAPACITY], Order_By_Divisors);
The generation of divisors is left as an exercise for the OP.
Reworking your code with std::sort:
std::vector<std::pair<int, int>> customSort(const std::vector<int>& v)
{
std::vector<std::pair<int, int>> ps;
ps.reserve(v.size());
// We don't have zip sort :/
// So building the pair
for (auto e : v)
{
ps.emplace_back(e, cntDiv(e));
}
std::sort(ps.begin(), ps.end(), [](const auto&lhs, const auto& rhs) {
// descending number of divisors, increasing value
return std::make_tuple(-lhs.second, lhs.first)
< std::make_tuple(-rhs.second, rhs.first);
});
return ps;
}
int main()
{
const std::vector<int> v = {12, 20, 4, 100, 13};
const auto res = customSort(v);
for(const auto& p : res)
{
std::cout << p.first << " ";
}
}
Demo

Algorithm to compute mode

I'm trying to devise an algorithm in the form of a function that accepts two parameters, an array and the size of the array. I want it to return the mode of the array and if there are multiple modes, return their average. My strategy was to take the array and first sort it. Then count all the occurrences of a number. while that number is occurring, add one to counter and store that count in an array m. So m is holding all the counts and another array q is holding the last value we were comparing.
For example: is my list is {1, 1, 1, 1, 2, 2, 2}
then i would have m[0] = 4 q[0] = 1
and then m[1] = 3 and q[1] = 2.
so the mode is q[0] = 1;
unfortunately i have had no success thus far. hoping someone could help.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, k = 0, counter = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
for(int j = 0; j < n; j++){
while(y[i] == y[j]) {
counter++;
i++;
}
}
m[k] = counter;
q[k] = y[i];
i--; //i should be 1 less since it is referring to an array subscript
k++;
counter = 0;
}
}
Even though you have some good answers already, I decided to post another. I'm not sure it really adds a lot that's new, but I'm not at all sure it doesn't either. If nothing else, I'm pretty sure it uses more standard headers than any of the other answers. :-)
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <map>
#include <iostream>
#include <utility>
#include <functional>
#include <numeric>
int main() {
std::vector<int> inputs{ 1, 1, 1, 1, 2, 2, 2 };
std::unordered_map<int, size_t> counts;
for (int i : inputs)
++counts[i];
std::multimap<size_t, int, std::greater<size_t> > inv;
for (auto p : counts)
inv.insert(std::make_pair(p.second, p.first));
auto e = inv.upper_bound(inv.begin()->first);
double sum = std::accumulate(inv.begin(),
e,
0.0,
[](double a, std::pair<size_t, int> const &b) {return a + b.second; });
std::cout << sum / std::distance(inv.begin(), e);
}
Compared to #Dietmar's answer, this should be faster if you have a lot of repetition in the numbers, but his will probably be faster if the numbers are mostly unique.
Based on the comment, it seems you need to find the values which occur most often and if there are multiple values occurring the same amount of times, you need to produce the average of these. It seems, this can easily be done by std::sort() following by a traversal finding where values change and keeping a few running counts:
template <int Size>
double mode(int const (&x)[Size]) {
std::vector<int> tmp(x, x + Size);
std::sort(tmp.begin(), tmp.end());
int size(0); // size of the largest set so far
int count(0); // number of largest sets
double sum(0); // sum of largest sets
for (auto it(tmp.begin()); it != tmp.end(); ) {
auto end(std::upper_bound(it, tmp.end(), *it));
if (size == std::distance(it, end)) {
sum += *it;
++count;
}
else if (size < std::distance(it, end)) {
size = std::distance(it, end);
sum = *it;
count = 1;
}
it = end;
}
return sum / count;
}
If you simply wish to count the number of occurences then I suggest you use a std::map or std::unordered_map.
If you're mapping a counter to each distinct value then it's an easy task to count occurences using std::map as each key can only be inserted once. To list the distinct numbers in your list simply iterate over the map.
Here's an example of how you could do it:
#include <cstddef>
#include <map>
#include <algorithm>
#include <iostream>
std::map<int, int> getOccurences(const int arr[], const std::size_t len) {
std::map<int, int> m;
for (std::size_t i = 0; i != len; ++i) {
m[arr[i]]++;
}
return m;
}
int main() {
int list[7]{1, 1, 1, 1, 2, 2, 2};
auto occurences = getOccurences(list, 7);
for (auto e : occurences) {
std::cout << "Number " << e.first << " occurs ";
std::cout << e.second << " times" << std::endl;
}
auto average = std::accumulate(std::begin(list), std::end(list), 0.0) / 7;
std::cout << "Average is " << average << std::endl;
}
Output:
Number 1 occurs 4 times
Number 2 occurs 3 times
Average is 1.42857
Here's a working version of your code. m stores the values in the array and q stores their counts. At the end it runs through all the values to get the maximal count, the sum of the modes, and the number of distinct modes.
float mode(int x[],int n)
{
//Copy array and sort it
int y[n], temp, j = 0, k = 0, m[n], q[n];
for(int i = 0; i < n; i++)
y[i] = x[i];
for(int pass = 0; pass < n - 1; pass++)
for(int pos = 0; pos < n; pos++)
if(y[pass] > y[pos]) {
temp = y[pass];
y[pass] = y[pos];
y[pos] = temp;
}
for(int i = 0; i < n;){
j = i;
while (y[j] == y[i]) {
j++;
}
m[k] = y[i];
q[k] = j - i;
k++;
i = j;
}
int max = 0;
int modes_count = 0;
int modes_sum = 0;
for (int i=0; i < k; i++) {
if (q[i] > max) {
max = q[i];
modes_count = 1;
modes_sum = m[i];
} else if (q[i] == max) {
modes_count += 1;
modes_sum += m[i];
}
}
return modes_sum / modes_count;
}

Sieve of Eratosthenes algorithm

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];
}
}