I wrote a OpenMP program in C++ which basically finds the suffix-prefix overlap of a given length. All my strings are stored in a vector and I have two for loops for checking the overlap (all against all). I am trying to make the for loop parallel, but it does not improve the time. Following is my program
vector<string> Reads; // contains all strings
vector<int> *AdjList = new vector<int>[Reads.size()];
vector<int> *OLL = new vector<int>[Reads.size()];
// int i,j;
/*# pragma omp parallel \
shared ( AdjList, OLL ) \
private ( i, j )*/
#pragma omp parallel for
for(int i=0; i<Reads.size(); i++){
string suff = Reads.at(i).substr(Reads.at(i).length() - minOLL, minOLL);
for(int j=0; j<Reads.size(); j++){
if(i != j){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
}
}
I guess reduction might help, but I am clueless about how to use it
1.since size of strings may be different you may use schedule(dynamic) so the tasks dynamically assigned to threads. 2. you can split inner loop into two loops to get rid of if statement. 3. substr is not a good choice because leads to creation of new string so you may use and save character positions to speed the code. However below applied 1, 2 mentioned cases:
#pragma omp parallel for schedule(dynamic)
for(int i=0; i<Reads.size(); i++){
string suff = Reads.at(i).substr(Reads.at(i).length() - minOLL, minOLL);
for(int j=0; j< i; j++){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
for(int j=i+1; j< Reads.size(); j++){
size_t found = rabin_karp(suff, Reads.at(j));
if(found != -1){
string pref1 = Reads.at(j).substr(0, found);
string suff1 = Reads.at(i).substr(Reads.at(i).length() - minOLL - found, found);
if(pref1.compare(suff1) == 0){
AdjList[i].push_back(j);
OLL[i].push_back(found + minOLL);
}
}
}
}
Here's an example.
#include "pch.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <omp.h>
using namespace std;
class Monitorius {
private:
int M[50];
int count = 0;
int suma = 0;
public:
Monitorius()
{
for (int i = 0; i < 50; i++)
M[i] = 0; // nusinulinamas masyvas
}
// Funkcijos ---------------------------------------
void Prideti(int skaicius)
{
#pragma omp critical
{
M[count] = skaicius;
count++;
Suma();
}
}
void Suma()
{
suma = 0;
for (int i = 0; i < 50; i++) {
suma += M[i];
}
cout << "Suma: " << suma << endl;
}
};
void paleistiGijas(Monitorius *monitorius) {
#pragma omp parallel num_threads(5)
{
for (int i = 1; i <= 10; i++) {
monitorius->Prideti(i);
}
}
}
int main()
{
// Monitoriaus sukurimas bei giju paleidimas
Monitorius *monitorius = new Monitorius();
// Pradedamas giju darbas
paleistiGijas(monitorius);
// Atlaisvinama atmintis
delete(monitorius);
return 0;
}
Related
The code gets an exception of type out of range and i don't know why. It seems to work when i debug it, teh string is converted to what i want it to be.
First time on stack overflow btw:)
#include <iostream>
using namespace std;
string s;
string alpha = "abcdefghijklmnopqrstuvwxyz";
string crypto(string& s);
int main()
{
cin >> s;
cout << crypto(s);
return 0;
}
string crypto(string& s)
{
size_t i = 0;
while (i < s.length()) {
for (size_t j = 0; j < alpha.length(); j++) {
if (s.at(i) == alpha.at(j)) {
s.at(i) = alpha.at(alpha.length() - 1 - j);
++i;
}
}
}
return s;
}
Think about the case: if s.length() < alpha.length().
The problem was the i++ at the wrong place. You should format your code better, then this is much easier to spot.
Also avoid non-constant global variables and using namespace std:
#include <iostream>
#include <string> //Include the headers you use
const std::string alpha="abcdefghijklmnopqrstuvwxyz";
void crypto(std::string &s);
int main(){
std::string s;
crypto(s);
std::cout<<s;
return 0;
}
void crypto(std::string &s) //If you take the string by reference, it is changed, so you do not have to return it
{
for(std::size_t i = 0; i < s.length(); ++i) { //The for loop avoids the mistake completely
for(size_t j=0; j < alpha.length(); ++j){
if(s.at(i)==alpha.at(j)){
s.at(i)=alpha.at(alpha.length()-1-j);
}
}
}
}
To not solve your problem completely, there is still a bug in the code, that was also in yours. Try to find the error yourself.
The i++ was not put at the right place.
Moreover, there is another issue in the code: once an element has been replaced, you must leave the inner loop immediately (break). If not, you can have a -> z -> a in the same loop.
Input
abcyz
Output
zyxba
abcyz
#include <iostream>
#include <string>
std::string crypto(std::string& s) {
const std::string alpha = "abcdefghijklmnopqrstuvwxyz";
for (size_t i = 0; i < s.length(); ++i) {
for (size_t j = 0; j < alpha.length(); j++) {
if (s.at(i) == alpha.at(j)) {
s.at(i) = alpha.at(alpha.length() - 1 - j);
break;
}
}
}
return s;
}
int main() {
std::string s;
std::cin >> s;
std::cout << crypto(s) << std::endl;
std::cout << crypto(s) << std::endl;
return 0;
}
The inner loop of the crypto function can increment i past the end of the string. There's no test to stop it.
You could avoid this by breaking out of the loop when a letter is changed (that's more correct and potentially faster). That then means you should increment i outside the inner loop which means the outer loop can be a for loop as well.
string crypto(string &s) {
for (size_t i = 0; i < s.length(); ++i) {
for (size_t j = 0; j < alpha.length(); ++j) {
if (s.at(i) == alpha.at(j)) {
s.at(i) = alpha.at(alpha.length() - 1 - j);
break;
}
}
}
return s;
}
I have written a program for an assignment that cracks passwords using a dictionary attack and am trying to speed it up using Open MPI but my Open MPI version is slower and I am not sure why or what I am not understanding. The encrypted passwords are generated using a salt and a string passed into the unix function 'crypt.'
From what I have learned from looking at my class lecture notes, this is what I have come up with.
main.cc:
//****************************************************
// File: main.cc
// Author: Jordan Ward
// Purpose: Crack passwords in the form word+number
// or number+word where number can be at most
// three digits long using
// Open MPI to make it more efficient.
//*****************************************************
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <unistd.h>
#include <mpi.h>
using namespace std;
// Builds the list of encrypted passwords,
// list of dictionary words, and list of salts.
void file_IO(int argc, char *argv[], vector<string> &encPass, vector<string> &words,
vector<string> &salts);
// Builds the list of possible guesses.
void build_guesses(vector<string> &guesses, vector<string> &words);
// Tries each of the salts with each of
// the strings in the list of guesses to see
// if they match the ecrypted passwords.
void crack(string pass, vector<string> &salts, vector<string> &guesses);
// Broadcasts the vectors to all other processes.
void broadcast_receive(vector<string> &encPass, vector<string> &words,
vector<string> &salts, vector<string> &guesses);
// Converts a vector of strings to a vector of chars
vector<char> convert(vector<string> &strings);
int main(int argc, char *argv[]) {
vector<string> encPass;
vector<string> words;
vector<string> salts;
vector<string> guesses;
int numProcesses;
int procNum;
MPI_Init(NULL, NULL);
MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); // Get the number of processes
MPI_Comm_rank(MPI_COMM_WORLD, &procNum); // Get the process number
if(procNum == 0) {
file_IO(argc, argv, encPass, words, salts);
build_guesses(guesses, words);
}
broadcast_receive(encPass, words, salts, guesses, numProcesses, procNum);
if(procNum != 0) {
for(size_t i = 0; i < encPass.size(); i++) {
if(i % procNum == 0) {
size_t del = encPass[i].rfind("$"); // Finds the last "$" in the string
string pass = encPass[i].substr(del); // Pass is a substring starting at the last "$"
crack(pass, salts, guesses);
}
}
}
MPI_Finalize();
return 0;
}
void file_IO(int argc, char *argv[], vector<string> &encPass, vector<string> &words,
vector<string> &salts) {
if(argc < 3) {
cout << "One or more files were not specified." << endl;
cout << "Correct format is 'mpiexec a.out file1 file2'" << endl;
exit(1);
}
ifstream secretPass(argv[1]);
string singlePass;
while(getline(secretPass, singlePass)) {
encPass.push_back(singlePass);
}
secretPass.close();
ifstream dictionary(argv[2]);
string word;
while(getline(dictionary, word)) {
words.push_back(word);
}
dictionary.close();
ifstream salt("salts");
string s;
while(getline(salt, s)) {
salts.push_back(s);
}
salt.close();
}
void build_guesses(vector<string> &guesses, vector<string> &words) {
//one word and one number
for(size_t i = 0; i < words.size(); i++) {
for(size_t j = 0; j < 10; j++) {
guesses.push_back(words[i] + to_string(j));
}
}
//one number and one word
for(size_t i = 0; i < 10; i++) {
for(size_t j = 0; j < words.size(); j++) {
guesses.push_back(to_string(i) + words[j]);
}
}
//one word and two numbers
for(size_t i = 0; i < words.size(); i++) {
for(size_t j = 0; j < 10; j++) {
for(size_t x = 0; x < 10; x++) {
guesses.push_back(words[i] + to_string(j) + to_string(x));
}
}
}
//two numbers and one word
for(size_t i = 0; i < 10; i++) {
for(size_t j = 0; j < 10; j++) {
for(size_t x = 0; x < words.size(); x++) {
guesses.push_back(to_string(i) + to_string(j) + words[x]);
}
}
}
//one word and three numbers
for(size_t i = 0; i < words.size(); i++) {
for(size_t j = 0; j < 10; j++) {
for(size_t x = 0; x < 10; x++) {
for(size_t y = 0; y < 10; y++) {
guesses.push_back(words[i] + to_string(j) + to_string(x) + to_string(y));
}
}
}
}
//three numbers and one word
for(size_t i = 0; i < 10; i++) {
for(size_t j = 0; j < 10; j++) {
for(size_t x = 0; x < 10; x++) {
for(size_t y = 0; y < words.size(); y++) {
guesses.push_back(to_string(i) + to_string(j) + to_string(x) + words[y]);
}
}
}
}
}
void crack(string pass, vector<string> &salts, vector<string> &guesses) {
for(size_t i = 0; i < salts.size(); i++) {
for(size_t j = 0; j < guesses.size(); j++) {
string ep = crypt(guesses[j].c_str(), salts[i].c_str());
if(ep.compare(salts[i] + pass) == 0) {
cout << "Password: " + guesses[j] << endl;
}
}
}
cout << "Password not found" << endl;
}
void broadcast_receive(vector<string> &encPass, vector<string> &words,
vector<string> &salts, vector<string> &guesses) {
int buffer[5];
buffer[0] = encPass.size();
buffer[1] = words.size();
buffer[2] = salts.size();
buffer[3] = guesses.size();
MPI_Bcast(buffer, 4, MPI_INT, 0, MPI_COMM_WORLD);
encPass.resize(buffer[0]);
words.resize(buffer[1]);
salts.resize(buffer[2]);
guesses.resize(buffer[3]);
vector<char> ep = convert(encPass);
vector<char> w = convert(words);
vector<char> s = convert(salts);
vector<char> g = convert(guesses);
MPI_Bcast(ep.data(), ep.size(), MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(w.data(), w.size(), MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(s.data(), s.size(), MPI_CHAR, 0, MPI_COMM_WORLD);
MPI_Bcast(g.data(), g.size(), MPI_CHAR, 0, MPI_COMM_WORLD);
}
vector<char> convert(vector<string> &strings) {
vector<char> cstrings;
cstrings.reserve(strings.size());
for(string s : strings) {
for(size_t i = 0; i < strlen(s.c_str()); i++) {
cstrings.push_back(s.c_str()[i]);
}
}
return cstrings;
}
My thought process is:
If process number is 0, read in the files and build the vectors with strings from the files and then build the list of guesses.
Else, receive all the lists and go through each encrypted password and see if any of the salts combined with any of the guesses matches the encrypted password.
What am I not doing correctly or not understanding that is making this slower than the original without the Open MPI code? Original code would just be the same file without the broadcast_receive and convert functions and obviously without the MPI calls in the main function.
I am compiling with mpic++ -std=c++11 -Wall main.cc -lcrypt and then running with mpiexec a.out enc_passwords words where enc_passwords is a small file with some encrypted passwords generated from the crypt function and words is a small list of words to build the guesses with.
Regarding your first question (why isn't MPI "faster"?), you need to ask two questions:
Q: Is the work actually being partitioned to multiple processors, in parallel?
Q: Does the overhead of message passing exceed the actual work you're trying to parallelize?
This should help with both questions:
OpenMPI FAQ: Performance Tools
Regarding your follow-on comment, "...but for some reason it is throwing a ton of errors.": please provide an MCVE. Or simply revert back to the "working" code.
I don't know how I can parallel this loops because I have a lot of dependent variables and I am very confused
can you help and guide me?
the number one is :
for (int a = 0; a < sigmaLen; ++a) {
int f = freq[a];
if (f >= sumFreqLB)
if (updateRemainingDistances(s, a, pos))
if (prunePassed(pos + 1)) {
lmer[pos] = a;
enumerateStrings(pos + 1, sumFreqLB - f);
}
}
The second one is :
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
for (int k = L; k; --k) {
int *dsn = dist[k] + pairOffset;
int *ds = dist[k - 1] + pairOffset;
int *s = colS[k - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
Really another one is :
void enumerateSubStrings(int rowNumber, int remainQTolerance) {
int nItems = rowSize[rowNumber][stackSz];
if (shouldGenerateNeighborhood(rowNumber, nItems)) {
bruteForceIt(rowNumber, nItems);
} else {
indexType *row = rowItem[rowNumber];
for (int j = 0; j < nItems; ++j) {
indexType ind = row[j];
addString(lmers + ind);
preprocessLowerBounds();
uint threshold = maxLB[stackSz] - addMaxFreq();
if (hasSolution(0, threshold)) {
if (getValid<hasPreprocessedPairs, useQ>(rowNumber + 1,
(stackSz <= 2 ? n : smallN), threshold + LminusD,
ind, remainQTolerance)) {
enumerateSubStrings<hasPreprocessedPairs, useQ>(
rowNumber + 1, remainQTolerance);
}
}
removeLastString();
}
}
void addString(const char *t) {
int *mf = colMf[stackSz + 1];
for (int j = 0; j < L; ++j) {
int c = t[j];
colS[j][stackSz] = c;
mf[j] = colMaxFreq[j] + (colMaxFreq[j] == colFreq[j][c]++);
}
colMaxFreq = mf;
++stackSz;
}
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
for (int k = L; k; --k) {
int *dsn = dist[k] + pairOffset;
int *ds = dist[k - 1] + pairOffset;
int *s = colS[k - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
}
void removeLastString() {
--stackSz;
for (int j = 0; j < L; ++j)
--colFreq[j][colS[j][stackSz]];
colMaxFreq = colMf[stackSz];
}
Ok, For OpenMP to parallelize a loop in your basically follow these two rules, the first never write in the same memory location from different threads and second rule never depend on the reading of a memory area that may modified another thread, Now in the first loop you just change the lmer variable and other operations are read-only variables that I assume are not changing at the same time from another part of your code, so the first loop would be as follows:
#pragma omp for private(s,a,pos) //According to my intuition these variables are global or belong to a class, so you must convert private to each thread, on the other hand sumFreqLB and freq not included because only these reading
for (int a = 0; a < sigmaLen; ++a) {
int f = freq[a];
if (f >= sumFreqLB)
if (updateRemainingDistances(s, a, pos))
if (prunePassed(pos + 1)) {
#pragma omp critical //Only one thread at a time can enter otherwise you will fail at runtime
{
lmer[pos] = a;
}
enumerateStrings(pos + 1, sumFreqLB - f);
}
}
In the second loop i could not understand how you're using the for, but you have no problems because you use only reads and only modified the thread local variables.
You must make sure that the functions updateRemainingDistances, prunePassed and enumerateStrings do not use static or global variables within.
In the following function you use most only read operations which can be done from multiple threads (if any thread modifying these variables) and write in local memory positions so just change the shape of the FOR for OpenMP can recognize that FOR.
void preprocessLowerBounds() {
int i = stackSz - 1;
int pairOffset = (i * (i - 1)) >> 1;
#pragma omp for
for (int var=0; var<=k-L; var++){
int newK=k-var;//This will cover the initial range and in the same order
int *dsn = dist[newK] + pairOffset;
int *ds = dist[newK - 1] + pairOffset;
int *s = colS[newK - 1];
char ci = s[i];
for (int j = 0; j < i; ++j) {
char cj = s[j];
*ds++ = (*dsn++) + (ci != cj);
}
}
In the last function you use many functions for which I do not know the source code and thus can not know if they are looking for parallelizable example below the following examples are wrong:
std::vector myVector;
void notParalelizable_1(int i){
miVector.push_back(i);
}
void notParalelizable_2(int i){
static int A=0;
A=A+i;
}
int varGlobal=0;
void notParalelizable_3(int i){
varGlobal=varGlobal+i;
}
void oneFunctionParalelizable(int i)
{
int B=i;
}
int main()
{
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_1(i);//Error because myVector is modified simultaneously from multiple threads, The error here is that myVector not store the values in ascending order as this necessarily being accesing by multiple threads, this more complex functions can generate erroneous results or even errors in run time.
}
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_2(i);//Error because A is modified simultaneously from multiple threads
}
#pragma omp for
for(int i=0;i<10;i++)
{
notParalelizable_3(i);//Error because varGlobal is modified simultaneously from multiple threads
}
#pragma omp for
for(int i=0;i<10;i++)
{
oneFunctionParalelizable(i);//no problem
}
//The following code is correct
int *vector=new int[10];
#pragma omp for
for(int i=0;i<10;i++)
{
vector[i]=i;//No problem because each thread writes to a different memory pocicion
}
//The following code is wrong
int k=2;
#pragma omp for
for(int i=0;i<10;i++)
{
k=k+i; //The result of the k variable at the end will be wrong as it is modified from different threads
}
return 0;
}
I have this code to do permutations of a string.
#include <iostream>
#include <string.h>
using namespace std;
/* Prototipo de función */
void Permutaciones(char *, int l=0);
void sort(string scadena[]);
//array global to copy all permutations and later sort
string array[900000];
int m=0;
int main() {
int casos;
cin>>casos;
char palabra[casos][13];
for(int i=0;i<casos;i++)
cin>>palabra[i];
for(int i=0;i<casos;i++){
m=0;
Permutaciones(palabra[i]);
sort(array);
}
sort(array);
system("pause");
return 0;
}
void sort(string scadena[]){
string temp;
for(int i=0;i<m;i++){
for(int j=i+1;j<m;j++){
if(scadena[i]>scadena[j]){
temp=scadena[i];
scadena[i]=scadena[j];
scadena[j]=temp;
}
}
}
for(int i=0;i<m;i++){
for(int j=1;j<m;j++){
if(scadena[i]==scadena[j] && j!=i){
for(int k=j;k <m; k++){
scadena[k]=scadena[k+1];
}
m--;
j--;
}
}
}
for(int i=0;i<m;i++){
cout<<scadena[i]<<endl;
}
}
void Permutaciones(char * cad, int l) {
char c; /* variable auxiliar para intercambio */
int i, j; /* variables para bucles */
int n = strlen(cad);
for(i = 0; i < n-l; i++) {
if(n-l > 2){
Permutaciones(cad, l+1);
}
else {
array[m]=cad;
m++;
}
/* Intercambio de posiciones */
c = cad[l];
cad[l] = cad[l+i+1];
cad[l+i+1] = c;
if(l+i == n-1) {
for(j = l; j < n; j++){
cad[j] = cad[j+1];
}
cad[n] = 0;
}
}
}
And the code generates all permutations fine, and later sorted the array and it works fine. But when i am intenting remove the repeated strings, the code show me somethings repeated, and not sorted.
Who can say me what is my error?
You could have accomplished it easier using standard library:
#include <algorithm>
using namespace std;
int main() {
int a[] = {1, 2, 5, 6, 7};
int n = 5;
do {
// print array a
} while (next_permutation(a, a + n));
}
Unless the task was to implement it on your own. And of course make sure your array is sorted before you try to permutate it in this way, otherwise you will miss some permutations.
HERE, is a simplest code for generating all combination/permutations of a given array without including some special libraries (only iostream.h and string are included) and without using some special namespaces than usual ( only namespace std is used).
void shuffle_string_algo( string ark )
{
//generating multi-dimentional array:
char** alpha = new char*[ark.length()];
for (int i = 0; i < ark.length(); i++)
alpha[i] = new char[ark.length()];
//populating given string combinations over multi-dimentional array
for (int i = 0; i < ark.length(); i++)
for (int j = 0; j < ark.length(); j++)
for (int n = 0; n < ark.length(); n++)
if( (j+n) <= 2 * (ark.length() -1) )
if( i == j-n)
alpha[i][j] = ark[n];
else if( (i-n)== j)
alpha[i][j] = ark[ ark.length() - n];
if(ark.length()>=2)
{
for(int i=0; i<ark.length() ; i++)
{
char* shuffle_this_also = new char(ark.length());
int j=0;
//storing first digit in golobal array ma
ma[v] = alpha[i][j];
//getting the remaning string
for (; j < ark.length(); j++)
if( (j+1)<ark.length())
shuffle_this_also[j] = alpha[i][j+1];
else
break;
shuffle_this_also[j]='\0';
//converting to string
string send_this(shuffle_this_also);
//checking if further combinations exist or not
if(send_this.length()>=2)
{
//review the logic to get the working idea of v++ and v--
v++;
shuffle_string_algo( send_this);
v--;
}
else
{
//if, further combinations are not possiable print these combinations
ma[v] = alpha[i][0];
ma[++v] = alpha[i][1];
ma[++v] = '\0';
v=v-2;
string disply(ma);
cout<<++permutaioning<<":\t"<<disply<<endl;
}
}
}
}
and main:
int main()
{
string a;
int ch;
do
{
system("CLS");
cout<<"PERMUNATING BY ARK's ALGORITH"<<endl;
cout<<"Enter string: ";
fflush(stdin);
getline(cin, a);
ma = new char[a.length()];
shuffle_string_algo(a);
cout<<"Do you want another Permutation?? (1/0): ";
cin>>ch;
} while (ch!=0);
return 0;
}
HOPE! it helps you! if you are having problem with understanding logic just comment below and i will edit.
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];
}
}