(C++) openmp leading to segmentation fault - c++
I'm new to using OpenMP on C++ and facing some issues with it:
#include <algorithm>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <numeric>
#include <string>
#include <vector>
#include <boost/multiprecision/cpp_int.hpp>
using namespace std;
using boost::multiprecision::cpp_int;
// generates prime numbers under n
vector<int> generatePrime(int n) {
vector<int> primes;
for (int i = 2; i <= n; i++) {
bool isPrime = true;
for (int j = 0; j < primes.size(); j++) {
if (i % primes[j] == 0) {
isPrime = false;
break;
}
}
if (isPrime) {
primes.push_back(i);
}
}
return primes;
}
// checks if an integer is a prime number
bool chkPrime(vector<int> vec, vector<int> ref) {
for (int i = 0; i < vec.size(); i++) {
if (find(ref.begin(), ref.end(), vec[i]) == ref.end()) {
return false;
}
}
return true;
}
int main() {
vector<int> primes = generatePrime(100);
vector<cpp_int> row(1, 1);
int maxAlleles = 1000;
vector<vector<int>> rowPrime;
for (int alleles = 1; alleles <= maxAlleles; alleles++) {
vector<cpp_int> row1 = row;
row1.push_back(0);
row1.push_back(0);
vector<cpp_int> row2 = row1;
vector<cpp_int> row3 = row1;
vector<cpp_int> rowFinal;
rotate(row2.begin(), row2.end() - 1, row2.end());
rotate(row3.begin(), row3.end() - 2, row3.end());
for (int i = 0; i < row1.size(); i++) {
// making the next row of the trinomial triangle
rowFinal.push_back(row1[i] + row2[i] + row3[i]);
}
row = rowFinal;
#pragma omp parallel for
// for each number in the row, we will make the number into a string and divide it by 2 letters
// and put it into a vector (splitTwo), starting from the beginning of the string
for (int num = 0; num < row.size(); num++) {
string item = to_string(row[num]);
vector<int> splitTwo;
int i = 0;
if (item.length() % 2 == 0) {
while (i <= item.length() - 2) {
splitTwo.push_back(stoi(item.substr(i, 2)));
i += 2;
}
}
else {
if (item.length() > 2) {
while (i <= item.length() - 3) {
splitTwo.push_back(stoi(item.substr(i, 2)));
i += 2;
}
}
int last_letter = item[item.length() - 1] - '0';
splitTwo.push_back(last_letter);
}
// we are going to push back splitTwo in rowPrime if all items in splitTwo are prime numbers
if (chkPrime(splitTwo, primes) == true) {
splitTwo.push_back(alleles);
splitTwo.push_back(num);
rowPrime.push_back(splitTwo);
}
}
}
vector<int> sum;
for (int k = 0; k < rowPrime.size(); k++) {
sum.push_back(
accumulate(begin(rowPrime[k]), end(rowPrime[k]) - 2, 0, plus<int>()));
}
int idx = distance(begin(sum), max_element(begin(sum), end(sum)));
for (int &i : rowPrime[idx]) {
cout << i << ' ';
}
cout << sum[idx] << ' ' << rowPrime.size();
return 0;
}
When I use pragma omp parallel for on the code above and make an executable file, it leads to different results each time I execute the code: either 1) outputs the answer properly, or 2) gives a segmentation fault error, or 3) gives a Incorrect checksum for freed object 0x7fd0ef904088: probably modified after being freed. Corrupt value: 0x0 malloc: *** set a breakpoint in malloc_error_break to debug error. When I remove pragma omp parallel for it does not give me these errors. Any suggestions?
Related
for loop done without meeting the condition I set
#include <iostream> #include <vector> using namespace std; int main() { int n = 5; int nums[] = {0 ,1}; if (n == 0) { return 0; } else if (n == 1) { return 1; } else{ for (int i = 2; i < n + 1; i++) { cout << i << endl; nums[i] = nums[i-2] + nums[i-1]; } return nums[n] } return 0; } It is just a simple fibonacci array, but my code only gives stdout one time and it is two. FYI: this code may not be correct to compute the nth term of fibonacci array, but i am strugglling with this for loop. I think the condition of i < n+1 is not meet, but why this for loop ends
nums[i] has size 2. You can't access nums[i] for i >= 2. An array doesn't grow. You can't change the size of an array. Use a std::vector. You've already included the header. A return statement finishes a function. In case of the main function it causes the program to stop. The return value of the main function by convention describes if the program was successful or errors occurred. You are returning return nums[n]; That's probably not your intention. I assume you want to print the vector. #include <iostream> #include <vector> using namespace std; int main() { int n = 5; std::vector<int> nums {0 ,1}; if (n == 0) { return 0; } else if (n == 1) { return 1; } else { nums.reserve(n + 1); for (int i = 2; i < n + 1; i++) { cout << i << '\n'; nums.emplace_back(nums[i-2] + nums[i-1]); } for (const auto num : nums) { cout << num << '\n'; } } return 0; }
it's because you can't access to nums[2] so the correct version of your code is : #include <iostream> #include <vector> using namespace std; int main() { int n = 5; int nums[5] = {0 ,1}; if (n == 0) { return 0; } else if (n == 1) { return 1; } else{ for (int i = 2; i < n + 1; i++) { cout << i << endl; nums[i] = nums[i-2] + nums[i-1]; } return nums[n] } return 0; }
you must provide estimated size to array or you will create vector or some dynamic array.. Your approach always give Segmentation fault; #include <iostream> #include <vector> using namespace std; int main() { int n = 5; vector<int> nums(n+1); nums[0]=0; nums[1]=1; if (n == 0) { return 0; } else if (n == 1) { return 1; } else{ for (int i = 2; i < n + 1; i++) { // cout << i << endl; nums[i] = nums[i-2] + nums[i-1]; } for(int i=0;i<n;i++) { cout<<nums[i]<<endl; } } return 0; } */
Program to print first 5 perfect numbers, is printing 2096128?? C++
So this program will print perfect numbers, but one of them, 2096128, is being printed for some reason? Would really appreciate some help figuring out what is happening! Thank you! I can't figure out why one non perfect number is finding it way into the sequence! #include <iostream> #include <string> #include <math.h> #include <iomanip> bool isPerfect(int n); using namespace std; int main() { long long perfect = 0; int first = 0; first = (pow(2, 2 - 1))*(pow(2, 2) - 1); cout << first << endl; for (int i = 3, j = 1; j < 5; i += 2) { if (isPerfect(i)) { perfect = (pow(2, i - 1)*(pow(2, i) - 1)); cout << perfect << endl; j++; } } // pause and exit getchar(); getchar(); return 0; } bool isPerfect(int n) { if (n < 2) { return false; } else if (n == 2) { return true; } else if (n % 2 == 0) { return false; } else { bool prime = true; for (int i = 3; i < n; i += 2) { if (n%i == 0) { prime = false; break; } } return prime; } }
You're pretty much complicating this task. Here's what I came up with: #include <iostream> using namespace std; bool isPerfect(long long n); int main() { int count = 5; long long sum = 1; for (int i = 3; count >= 0; i += 2) { sum += i * i * i; if (isPerfect(sum)) { cout << sum << endl; count--; } } system("pause"); return 0; } bool isPerfect(long long n) { int sum = 0; for (int i = 1; i < n; i++) { if (n % i == 0) sum += i; } return sum == n; } It sure isn't perfect, but will do for 5 numbers. Consider that it'll be very slow for more than 5 numbers.
Classis task for splitting weights into 2 trucks (C++) (Dynamic Programming)
I have a task that by given line of weights of cages and I have to split them into 2 trucks. The split should be done like this that |a - b| to have least value where 'a' is the common weight of the cages in the first truck and 'b' is the common weight of the cages of second truck. My program seems to work but when I upload it to hackerrank abort function is called. So where is my fault? Here is the code: #include <iostream> #include <vector> #include <sstream> #include <cstring> using namespace std; int main() { string input; int k; while (getline(cin, input)) { /* splitting the input into integers */ vector<int> v; istringstream iss(input); while (iss >> k) v.push_back(k); /* --- II --- */ unsigned long sum = 0; unsigned i, j; for (i = 0; i < v.size(); i++) sum += v[i]; vector<char> can; can.push_back(1); for (i = 1; i <= sum; i++) can[i] = 0; for (i = 0; i < v.size(); i++) { for (j = sum; j+1 > 0; j--) { if (can[j]) { can[j + v[i]] = 1; } } } for (i = sum / 2; i > 1; i--) { if (can[i]) { if (i <= sum - i) { cout << i << " " << sum - i << endl; break; } else { cout << "a should be <= b"; break; } } } } return 0; }
How can this work? You create an empty vector of char, push one single value into it and that try to assign value passed the first: ... vector<char> can; can.push_back(1); // can contains one single value for (i = 1; i <= sum; i++) can[i] = 0; // Error "vector subscript out of range" in debug mode If you do not ask the control of vector subscript you will just invoke undefined behaviour. But if you just want to expand the vector, you can repeatedly can push_back: for (i = 1; i <= sum; i++) can.push_back(0);
Given an integer N, print numbers from 1 to N in lexicographic order
I'm trying to print the numbers from 1 to N in lexicographic order, but I get a failed output. for the following input 100, I get the 100, but its shifted and it doesn't match with the expected output, there is a bug in my code but I can not retrace it. class Solution { public: vector<int> lexicalOrder(int n) { vector<int> result; for(int i = 1; i <= 9; i ++){ int j = 1; while( j <= n){ for(int m = 0; m < j ; ++ m){ if(m + j * i <= n){ result.push_back(m+j*i); } } j *= 10; } } return result; } }; Input: 100 Output: [1,10,11,12,13,14,15,16,17,18,19,100,2,20,21,22,23,24,25,26,27,28,29,3,30,31,32,33,34,35,36,37,38,39,4,40,41,42,43,44,45,46,47,48,49,5,50,51,52,53,54,55,56,57,58,59,6,60,61,62,63,64,65,66,67,68,69,7,70,71,72,73,74,75,76,77,78,79,8,80,81,82,83,84,85,86,87,88,89,9,90,91,92,93,94,95,96,97,98,99] Expected: [1,10,100,11,12,13,14,15,16,17,18,19,2,20,21,22,23,24,25,26,27,28,29,3,30,31,32,33,34,35,36,37,38,39,4,40,41,42,43,44,45,46,47
Think about when i=1,j=10 what will happen in for(int m = 0; m < j ; ++ m){ if(m + j * i <= n){ result.push_back(m+j*i); } } Yes,result will push_back 10(0+10*1),11(1+10*1),12(2+10*1).. Here is a solution: #include <iostream> #include <vector> #include <string> std::vector<int> fun(int n) { std::vector<std::string> result; for (int i = 1; i <= n; ++i) { result.push_back(std::to_string(i)); } std::sort(result.begin(),result.end()); std::vector<int> ret; for (auto i : result) { ret.push_back(std::stoi(i)); } return ret; } int main(int argc, char *argv[]) { std::vector<int> result = fun(100); for (auto i : result) { std::cout << i << ","; } std::cout << std::endl; return 0; }
You are looping through all 2 digit numbers starting with 1 before outputting the first 3 digit number, so your approach won't work. One way to do this is to output the digits in base 11, padded out with leading spaces to the maximum number of digits, in this case 3. Output 0 as a space, 1 as 0, 2 as 1 etc. Reject any numbers that have any non-trailing spaces in this representation, or are greater than n when interpreted as a base 10 number. It should be possible to jump past multiple rejects at once, but that's an unnecessary optimization. Keep a count of the numbers you have output and stop when it reaches n. This will give you a lexicographical ordering in base 10. Example implementation that uses O(1) space, where you don't have to generate and sort all the numbers up front before you can output the first one: void oneToNLexicographical(int n) { if(n < 1) return; // count max digits int digits = 1, m = n, max_digit11 = 1, max_digit10 = 1; while(m >= 10) { m /= 10; digits++; max_digit11 *= 11; max_digit10 *= 10; } int count = 0; bool found_n = false; // count up starting from max_digit * 2 (first valid value with no leading spaces) for(int i = max_digit11 * 2; ; i++) { int val = 0, trailing_spaces = 0; int place_val11 = max_digit11, place_val10 = max_digit10; // bool valid_spaces = true; for(int d = 0; d < digits; d++) { int base11digit = (i / place_val11) % 11; if(base11digit == 0) { trailing_spaces++; val /= 10; } else { // if we got a non-space after a space, it's invalid // if(trailing_spaces > 0) // { // valid_spaces = false; // break; // trailing spaces only // } val += (base11digit - 1) * place_val10; } place_val11 /= 11; place_val10 /= 10; } // if(valid_spaces && (val <= n)) { cout << val << ", "; count++; } if(val == n) { found_n = true; i += 10 - (i % 11); // skip to next number with one trailing space } // skip past invalid numbers: // if there are multiple trailing spaces then the next run of numbers will have spaces in the middle - invalid if(trailing_spaces > 1) i += (int)pow(11, trailing_spaces - 1) - 1; // if we have already output the max number, then all remaining numbers // with the max number of digits will be greater than n else if(found_n && (trailing_spaces == 1)) i += 10; if(count == n) break; } } This skips past all invalid numbers, so it's not necessary to test valid_spaces before outputting each. The inner loop can be removed by doing the base11 -> base 10 conversion using differences, making the algorithm O(N) - the inner while loop tends towards a constant: int val = max_digit10; for(int i = max_digit11 * 2; ; i++) { int trailing_spaces = 0, pow11 = 1, pow10 = 1; int j = i; while((j % 11) == 0) { trailing_spaces++; pow11 *= 11; pow10 *= 10; j /= 11; } int output_val = val / pow10; if(output_val <= n) { cout << output_val << ", "; count++; } if(output_val == n) found_n = true; if(trailing_spaces > 1) { i += (pow11 / 11) - 1; } else if(found_n && (trailing_spaces == 1)) { i += 10; val += 10; } else if(trailing_spaces == 0) val++; if(count == n) break; } Demonstration The alternative, simpler approach is just to generate N strings from the numbers and sort them.
Maybe more general solution? #include <vector> #include <algorithm> using namespace std; // returns true is i1 < i2 according to lexical order bool lexicalLess(int i1, int i2) { int base1 = 1; int base2 = 1; for (int c = i1/10; c > 0; c/=10) base1 *= 10; for (int c = i2/10; c > 0; c/=10) base2 *= 10; while (base1 > 0 && base2 > 0) { int d1 = i1 / base1; int d2 = i2 / base2; if (d1 != d2) return (d1 < d2); i1 %= base1; i2 %= base2; base1 /= 10; base2 /= 10; } return (base1 < base2); } vector<int> lexicalOrder(int n) { vector<int> result; for (int i = 1; i <= n; ++i) result.push_back(i); sort(result.begin(), result.end(), lexicalLess); return result; } The other idea for lexicalLess(...) is to convert integers to string before comparision: #include <vector> #include <algorithm> #include <string> #include <boost/lexical_cast.hpp> using namespace std; // returns true is i1 < i2 according to lexical order bool lexicalLess(int i1, int i2) { string s1 = boost::lexical_cast<string>(i1); string s2 = boost::lexical_cast<string>(i2); return (s1 , s2); } You need Boost to run the second version.
An easy one to implement is to convert numbers to string, them sort the array of strings with std::sort in algorithm header, that sorts strings in lexicographical order, then again turn numbers to integer Make a vector of integers you want to sort lexicographically, name it numbers. Make an other vector and populate it strings of numbers in the first vector. name it strs. Sort strs array.4. Convert strings of strs vector to integers and put it in vectors List item #include <cstdlib> #include <string> #include <algorithm> #include <vector> #include <iostream> using namespace std; string int_to_string(int x){ string ret; while(x > 0){ ret.push_back('0' + x % 10); x /= 10; } reverse(ret.begin(), ret.end()); return ret; } int main(){ vector<int> ints; ints.push_back(1); ints.push_back(2); ints.push_back(100); vector<string> strs; for(int i = 0; i < ints.size(); i++){ strs.push_back(int_to_string((ints[i]))); } sort(strs.begin(), strs.end()); vector<int> sorted_ints; for(int i = 0; i < strs.size(); i++){ sorted_ints.push_back(atoi(strs[i].c_str())); } for(int i = 0; i < sorted_ints.size(); i++){ cout<<sorted_ints[i]<<endl; } }
As the numbers are unique from 1 to n, you can use a set of size n and insert all of them into it and then print them out. set will automatically keep them sorted in lexicographical order if you store the numbers as a string. Here is the code, short and simple: void lexicographicalOrder(int n){ set<string> ans; for(int i = 1; i <= n; i++) ans.insert(to_string(i)); for(auto ele : ans) cout <<ele <<"\n"; }
least number of digits without duplicates
I am a C++ noob. I have a list of numbers that I put into a Vector. All numbers are 9 digit integers and are unique. I want to know what is the least amount of digits (starting from the right) that can be used to uniquily identify each number in the set. right now there are only 6 numbers, but the list could potentially grow into the thousands. I have posted my code thus far (not working.) EDIT output is the following... digit is 1 digit is 1 digit is 1 RUN FINISHED; exit value 0; real time: 0ms; user: 0ms; system: 0ms This is mostly a learning exercise. Please be generous and explicit with your comments and solutions. #include <iostream> #include <vector> #include <fstream> #include <string> #include <cstdlib> #include <algorithm> using namespace std; int main() { //declare stream variable and load vector with values ifstream myfile("mydata.txt"); vector<int> myVector; int num; while (myfile >> num) { myVector.push_back(num); } //sort and squack if there is a duplicate. std::sort(myVector.begin(), myVector.end()); for (int i = 0; i < (myVector.size() - 1); i++) { if (myVector.at(i) == myVector.at(i + 1)) { printf("There are duplicate student numbers in the file"); exit(EXIT_FAILURE); } } //if it get here, then there are no duplicates of student numbers vector<int> newv; int k = 1; bool numberFound = false; bool myflag = false; while (numberFound == false) { //loop through original numbers list and add a digit to newv. for (int j = 0; j < myVector.size(); ++j) { newv.push_back(myVector.at(j) % (10^k)); } sort(newv.begin(), newv.end()); for (int i = 0; i < (newv.size() - 1); i++) { if (newv.at(i) == newv.at(i + 1)) { //there is a duplicate for this digit. Set flag. myflag = true; } if (myflag == false) { numberFound = true; cout << "digit is " << k << endl; } else { k++; } } } // for (int i = 0; i < myVector.size(); i++) { // cout << "||" << myVector.at(i) << "||" << endl; // } // // for (int i = 0; i < newv.size(); i++) { // cout << "---" << newv.at(i) << "---" << endl; // } return 0; }
Check the below code. #include <iostream> #include <vector> #include <fstream> #include <string> #include <cstdlib> #include <algorithm> #include <math.h> using namespace std; int main() { //declare stream variable and load vector with values ifstream myfile("mydata.txt"); vector<int> myVector; int num; while (myfile >> num) { myVector.push_back(num); } //sort and squack if there is a duplicate. std::sort(myVector.begin(), myVector.end()); for (int i = 0; i < (myVector.size() - 1); i++) { if (myVector.at(i) == myVector.at(i + 1)) { printf("There are duplicate student numbers in the file"); exit(EXIT_FAILURE); } } //if it get here, then there are no duplicates of student numbers vector<int> newv; int k = 1; bool numberFound = false; bool myflag = false; int p = 1; while (numberFound == false) { //loop through original numbers list and add a digit to newv. newv.clear(); p = p * 10; for (int j = 0; j < myVector.size(); ++j) { newv.push_back(myVector[j] % p); } sort(newv.begin(), newv.end()); myflag = false; for (int i = 0; i < (newv.size() - 1); i++) { if ( newv[i] == newv[i+1]) { //there is a duplicate for this digit. Set flag. myflag = true; break; } } if (myflag == true){ k ++; }else{ numberFound = true; cout << "digit is " << k << endl; break; } } return 0; } Sample Input: 123451789 123456687 125456789 123456780 Output: digit is 4