I am asking again with details:
https://stackoverflow.com/questions/33265241/reason-of-segmentation-fault-while-sorting?noredirect=1#comment54333476_33265241
What is the problem in this comparator?
inline bool comp(const vector<int>& a,const vector<int>& b){
for(int i=0;i<a.size() and i<b.size();i++){
if(a[i]<b[i])return 1;
if(a[i]>b[i])return 0;
}
return a.size()<=b.size();
}
I am getting segmentation fault while sorting a vector<vector<int> > using this function as comparator method?
EDIT : Sorry for putting the non-detailed question.
here is the problem statement from interviewbit
https://www.interviewbit.com/courses/programming/topics/backtracking/problems/comb/
inline bool comp(const vector<int>& a,const vector<int>& b){
for(int i=0;i<a.size() and i<b.size();i++){
if(a[i]<b[i])return 1;
if(a[i]>b[i])return 0;
}
return a.size()<=b.size();
}
vector<vector<int> > Solution::combinationSum(vector<int> &A, int B) {
std::sort(A.begin(), A.end());
A.erase(
std::unique(A.begin(), A.end()),
A.end());
/// T[i] : tells us if target i can be achieved or not.
bool T[B+1];
fill(T,T+B+1,0);
T[0]=1;
for(int i=1;i<=B;i++){
for(int j=0;j<A.size() and !T[i];j++){
if(i-A[j]>=0 and T[i-A[j]]){
T[i]=1;
}
}
}
/// Final answer is r[B];
vector< vector<int> > r[B+1];
r[0].push_back(vector<int>());
for(int i=1;i<=B;i++){
if(T[i]){
for(int j=0;j<A.size();j++){
if(i-A[j]>=0 and T[i-A[j]]){
for(int k=0; k<r[i-A[j]].size() ;k++){
vector<int> d=r[ i-A[j] ][ k ];
d.push_back(A[j]);
r[i].push_back(d);
}
}
}
}
}
for(int i=0;i<r[B].size();i++){
sort(r[B][i].begin(),r[B][i].end());
}
cerr << "comming here " << endl;
sort(r[B].begin(),r[B].end(),comp);
cerr << "not reaching here " << endl;
if(r[B].size()==0)return r[B];
vector< vector<int> > ans(1,r[B][0]);
for(int i=1;i<r[B].size();i++){
if(!comp(r[B][i],r[B][i-1])){
ans.push_back(r[B][i]);
}
}
return ans;
}
This code was giving seg fault for input
A : [ 10, 14, 4, 8, 19, 10, 5, 7, 20, 11 ]
B : 31
but on my computer I worked fine.
PS : later I realized that std::vector has < operator and > operator defined which sorts all the vectors in lexicographic order.
sort(r[B].begin(),r[B].end());
Now I wonder why's there segfault on interviewbit platform and not my pc.
General question: What is the reason for these segmentation faults due to bad comparison functions.
for any comparison function f, such that f(a,b) and f(b,a) both returns 0, It will lead to segfault in most cases.
To stack overflow : what is the problem with you guys, you don't let my questions stand for a few hours. Please, before putting anything to hold just think that the user may update the question soon with some more information. Let question stay for at least 24 hrs. Some of us sleep at "night". I asked this question because sometimes bad comparators in sorting can segmentation faults.
Related
I have to make a program that sorts 15 numbers from greatest to least, and then list the top five. Ive gotten some of it done. can someone help me on how to list the top five numbers?
#include <iostream>
using namespace std;
#define MAX 100
int main()
{
int arr[MAX];
int n,i,j;
int temp;
cout<<"Enter how many numbers to read: ";
cin>>n;
for(i=0;i<n;i++)
{
cout<<"Enter "<<i+1<<" number ";
cin>>arr[i];
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(arr[i]<arr[j])
{
temp =arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
cout<<"largest to smallest:"<<endl;
for(i=0;i<n;i++)
cout<<arr[i]<<"\t";
cout<<endl;
cout <<"the top five numbers are:"<< endl;
return 0;
}
Well you have already sorted it in descending order.
So to get the top 5, you just have to print the first 5 numbers in your array.
for (i=0; i<5; i++) cout << arr[i] << endl;
If you only need to have the top 5 elements, it is not necessary to sort the whole array. You can do a std::partial_sort to just have top 5 elements.
std::partial_sort(
std::begin(arr),
std::begin(arr) + 5,
std::end(arr),
[](int x, int y) { return x > y; });
Alice is playing an arcade game and wants to climb to the top of the leaderboard and wants to track her ranking. Its leaderboard works like this:
-The player with the highest score is ranked number on the leaderboard.
-Players who have equal scores receive the same ranking number, and the next player(s) receive the immediately following ranking number.
For example, the four players on the leaderboard have high scores of 100, 90, 90 and 80. Those players will have ranks 1, 2, 2 and 3 respectively. If Alice's scores are 70, 80 and 105 her rankings after each game are 4th, 3rd and 1st.
#include <bits/stdc++.h>
using namespace std;
struct table{
int rank;
int score;
};
This is a modified binary search function iplementation for searching the score.
int search(vector<table> v,int low,int high,int n,int x){
if(low<=high){
int mid =(high+low)/2;
if((v[mid].score==x) || (mid==0 && v[mid].score<x))
return v[mid].rank;
if(mid==n-1 && v[mid].score>x)
return (v[mid].rank + 1);
if(v[mid].score>x && x>v[mid+1].score && mid<n-1)
return v[mid+1].rank;
if(v[mid].score>x)
return search(v,mid+1,high,n,x);
else
return search(v,low,mid-1,n,x);
}
return -1;
}
Main climbingLeaderboard function
vector<int> climbingLeaderboard(vector<int> scores, vector<int> alice) {
vector<table> v;
vector<int> res;
int n = scores.size();
int m = alice.size();
int x=1;
for(int i=0 ; i<n ; i++){
if(scores[i]!=scores[i-1] && i>0)
x++;
v[i].rank = x;
v[i].score = scores[i];
}
int z;
for(int i=0 ; i<m ; i++){
x=alice[i];
z = search(v,0,n-1,n,x);
res.push_back(z);
}
return res;
}
Driver Program
int main(){
int scores_count;
cin >> scores_count;
vector<int> scores; `//vector for storing leaderboard scores`
int k;
for(int i=0 ; i<scores_count ; i++){
cin >> k;
scores.push_back(k);
}
int game_count; `//number of games played by alice`
vector<int> Alice; `//vector for storing Alice's scores`
for(int i=0 ; i<game_count ; i++){
cin >> k;
alice.push_back(k);
}
vector<int> result; `//vector for storing result rank of each game of Alice`
result = climbingLeaderboard(scores,alice);
for(auto i = result.begin() ; i!=result.end() ; i++){
cout << *i << endl;
}
return 0;
}
Problem: In your climbingLeaderboard function, the first loop will attempt to access scores[i-1] when i is set to 0, resulting in a negative index for a std::vector access.
Fix: Change the for loop to start from i=1.
Problem 2: You access v by index without instantiating any structures to hold the data (e.g. v[i].rank = x).
Fix 2: Create an instance of the structure and write the data to it, then push it back into the vector v. Alternatively, reserve the memory for the whole vector as a preallocation.
Problem 3: On closer inspection, your search functionality is definitely broken. You should probably test this in isolation from the rest of the code.
Core Dump/Segmentation fault is a specific kind of error caused by accessing memory that does not belong to you.
Error in function:Main climbingLeaderboard function:
Accessing out of array index bounds
Start Loop From I =1 as you are doing score[i-1] which here in the first iteration would score[-1] (index) and there is no -1 index in c++
for(int i=1; i<n ; i++){
if(scores[i]!=scores[i-1] && i>0)
x++;
v[i].rank = x;
v[i].score = scores[i];
}
I am trying to write a simple nonogram solver, in a kind of bruteforce way, but I am stuck on a relatively easy task. Let's say I have a row with clues [2,3] that has a length of 10
so the solutions are:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$-
$$-----$$$
-$$----$$$
--$$---$$$
---$$--$$$
----$$-$$$
-$$---$$$-
--$$-$$$--
I want to find all the possible solutions for a row
I know that I have to consider each block separately, and each block will have an availible space of n-(sum of remaining blocks length + number of remaining blocks) but I do not know how to progress from here
Well, this question already have a good answer, so think of this one more as an advertisement of python's prowess.
def place(blocks,total):
if not blocks: return ["-"*total]
if blocks[0]>total: return []
starts = total-blocks[0] #starts = 2 means possible starting indexes are [0,1,2]
if len(blocks)==1: #this is special case
return [("-"*i+"$"*blocks[0]+"-"*(starts-i)) for i in range(starts+1)]
ans = []
for i in range(total-blocks[0]): #append current solutions
for sol in place(blocks[1:],starts-i-1): #with all possible other solutiona
ans.append("-"*i+"$"*blocks[0]+"-"+sol)
return ans
To test it:
for i in place([2,3,2],12):
print(i)
Which produces output like:
$$-$$$-$$---
$$-$$$--$$--
$$-$$$---$$-
$$-$$$----$$
$$--$$$-$$--
$$--$$$--$$-
$$--$$$---$$
$$---$$$-$$-
$$---$$$--$$
$$----$$$-$$
-$$-$$$-$$--
-$$-$$$--$$-
-$$-$$$---$$
-$$--$$$-$$-
-$$--$$$--$$
-$$---$$$-$$
--$$-$$$-$$-
--$$-$$$--$$
--$$--$$$-$$
---$$-$$$-$$
This is what i got:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
typedef std::vector<bool> tRow;
void printRow(tRow row){
for (bool i : row){
std::cout << ((i) ? '$' : '-');
}
std::cout << std::endl;
}
int requiredCells(const std::vector<int> nums){
int sum = 0;
for (int i : nums){
sum += (i + 1); // The number + the at-least-one-cell gap at is right
}
return (sum == 0) ? 0 : sum - 1; // The right-most number don't need any gap
}
bool appendRow(tRow init, const std::vector<int> pendingNums, unsigned int rowSize, std::vector<tRow> &comb){
if (pendingNums.size() <= 0){
comb.push_back(init);
return false;
}
int cellsRequired = requiredCells(pendingNums);
if (cellsRequired > rowSize){
return false; // There are no combinations
}
tRow prefix;
int gapSize = 0;
std::vector<int> pNumsAux = pendingNums;
pNumsAux.erase(pNumsAux.begin());
unsigned int space = rowSize;
while ((gapSize + cellsRequired) <= rowSize){
space = rowSize;
space -= gapSize;
prefix.clear();
prefix = init;
for (int i = 0; i < gapSize; ++i){
prefix.push_back(false);
}
for (int i = 0; i < pendingNums[0]; ++i){
prefix.push_back(true);
space--;
}
if (space > 0){
prefix.push_back(false);
space--;
}
appendRow(prefix, pNumsAux, space, comb);
++gapSize;
}
return true;
}
std::vector<tRow> getCombinations(const std::vector<int> row, unsigned int rowSize) {
std::vector<tRow> comb;
tRow init;
appendRow(init, row, rowSize, comb);
return comb;
}
int main(){
std::vector<int> row = { 2, 3 };
auto ret = getCombinations(row, 10);
for (tRow r : ret){
while (r.size() < 10)
r.push_back(false);
printRow(r);
}
return 0;
}
And my output is:
$$-$$$----
$$--$$$---
$$---$$$--
$$----$$$--
$$-----$$$
-$$-$$$----
-$$--$$$--
-$$---$$$-
-$$----$$$-
--$$-$$$--
--$$--$$$-
--$$---$$$
---$$-$$$-
---$$--$$$
----$$-$$$
For sure, this must be absolutely improvable.
Note: i did't test it more than already written case
Hope it works for you
I was solving this problem on codeforces here, the code displays right answer but it exceeds the memory limit on the site. I can't figure out why. Also tried to use vectors but it doesn't work.
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,a,b,c,deny=0;
int groups[n];
scanf("%d %d %d",&n,&a,&b);
for(int i=0;i<n;i++){
cin>>groups[i];
}
int two_one=b*2;
//two kinds of tables:one seater,2 seater
//find no of ppl denied service
for(int j=0;j<n;j++){
if(groups[j]==1 and a!=0){
a-=1;
}
else if(groups[j]==1 and a==0){
two_one-=1;
b-=1;
}
else if(groups[j]==1 and a==0 and two_one==0){
deny+=1;
}
else if(groups[j]==2 and b!=0){
b-=1;
}
else if(groups[j]==2 and b==0){
deny+=2;
}
}
printf("%d",deny);
return 0;
}
It looks like you are trying to allocate an array before reading its size:
int n,a,b,c,deny=0; // <------ Unknown n value
int groups[n]; // <----- Allocation of array of n: undefined behavior
scanf("%d %d %d",&n,&a,&b); // <------ Reading 'groups' size
Just swap the last two lines.
Edit: according to the C++ standard, you should be using vectors:
int n,a,b,c,deny=0;
scanf("%d %d %d",&n,&a,&b);
std::vector<int> groups(n);
I am learning OPENMP and wrote the following code to solve nqueens problem.
//Full Code: https://github.com/Shafaet/Codes/blob/master/OPENMP/Parallel%20N- Queen%20problem.cpp
int n;
int call(int col,int rowmask,int dia1,int dia2)
{
if(col==n)
{
return 1;
}
int row,ans=0;
for(row=0;row<n;row++)
{
if(!(rowmask & (1<<row)) & !(dia1 & (1<<(row+col))) & !(dia2 & (1<<((row+n-1)-col))))
{
ans+=call(col+1,rowmask|1<<row,dia1|(1<<(row+col)), dia2|(1<<((row+n-1)-col)));
}
}
return ans;
}
double parallel()
{
double st=omp_get_wtime();
int ans=0;
int i;
int rowmask=0,dia1=0,dia2=0;
#pragma omp parallel for reduction(+:ans) shared(i,rowmask)
for(i=0;i<n;i++)
{
rowmask=0;
dia1=0,dia2=0;
int col=0,row=i;
ans+=call(1,rowmask|1<<row,dia1|(1<<(row+col)), dia2|(1<<((row+n-1)-col)));
}
printf("Found %d configuration for n=%d\n",ans,n);
double en=omp_get_wtime();
printf("Time taken using openmp %lf\n",en-st);
return en-st;
}
double serial()
{
double st=omp_get_wtime();
int ans=0;
int i;
int rowmask=0,dia1=0,dia2=0;
for(i=0;i<n;i++)
{
rowmask=0;
dia1=0,dia2=0;
int col=0,row=i;
ans+=call(1,rowmask|1<<row,dia1|(1<<(row+col)), dia2|(1<<((row+n-1)-col)));
}
printf("Found %d configuration for n=%d\n",ans,n);
double en=omp_get_wtime();
printf("Time taken without openmp %lf\n",en-st);
return en-st;
}
int main()
{
double average=0;
int count=0;
for(int i=2;i<=13;i++)
{
count++;
n=i;
double stime=serial();
double ptime=parallel();
printf("OpenMP is %lf times faster for n=%d\n",stime/ptime,n);
average+=stime/ptime;
puts("===============");
}
printf("On average OpenMP is %lf times faster\n",average/count);
return 0;
}
Parallel code is already faster than normal one but i wonder how can i optimize it more using openmp pragmas. I want to know what i should do for better performance and what i should not do.
Thanks in advance.
(Please dont suggest any optimizations which are non-related to parallel programming)
Your code seems to use classic backtracking N-Queens recursive algorithm, which is not the fastest possible for N-Queens solving, but (due to simplicity) is the most vivid one in terms of practicing with parallelism basics.
That's being said: this is very simple, thus you don't expect it to naturally demonstrate lots of advanced OpenMP means except basic "parallel for" and reduction.
But, as far as you're looking for learning parallelism and probably for more clearness and better learning curve, there is one more (out of many possible) implementation available, which uses the same algorithm but tends to be more readable and vivid from educational perspective:
void setQueen(int queens[], int row, int col) {
//check all previously placed rows for attacks
for(int i=0; i<row; i++) {
// vertical attacks
if (queens[i]==col) {
return;
}
// diagonal attacks
if (abs(queens[i]-col) == (row-i) ) {
return;
}
}
// column is ok, set the queen
queens[row]=col;
if(row==size-1) {
#pragma omp atomic
nrOfSolutions++; //Placed final queen, found a solution
}
else {
// try to fill next row
for(int i=0; i<size; i++) {
setQueen(queens, row+1, i);
}
}
}
//Function to find all solutions for nQueens problem on size x size chessboard.
void solve() {
#pragma omp parallel for
for(int i=0; i<size; i++) {
// try all positions in first row
int * queens = new int[size]; //array representing queens placed on a chess board. Index is row position, value is column.
setQueen(queens, 0, i);
delete[](queens);
}
}
This given code is one of Intel Advisor XE samples (for both C++ and Fortran); the parallelization aspects for given sample are discussed in very detailed manner in Chapter 10 of given Parallel Programming Book (in fact, given chapter just uses N-Queens to demonstrate how to use tools in order to parallelize serial code in general).
Given Advisor n-queens sample uses essentially the same algorithm as yours, but it replaces explicit reduction with combination of simple parallel for + atomic. This code is expected to be less efficient, but more "procedural-style" and more "educational", since it demonstrates "hidden" data race. In case you upload given samplecode, you will actually find 4 equialent N-Queens parallel implementatons using TBB, Cilk Plus and OpenMP (OMP is for C++ and Fortran).
I know I am a little late for the party, but you can use task queueing for further optimization.(about 7-10% faster results).No idea why. Here's the code,that i am using :
#include <iostream> // std::cout, cin, cerr ...
#include <iomanip> // modify std::out
#include <omp.h>
using namespace std;
int nrOfSolutions=0;
int size=0;
void print(int queens[]) {
cerr << "Solution " << nrOfSolutions << endl;
for(int row=0; row<size; row++) {
for(int col=0; col<size; col++) {
if(queens[row]==col) {
cout << "Q";
}
else {
cout << "-";
}
}
cout << endl;
}
}
void setQueen(int queens[], int row, int col, int id) {
for(int i=0; i<row; i++) {
// vertical attacks
if (queens[i]==col) {
return;
}
// diagonal attacks
if (abs(queens[i]-col) == (row-i) ) {
return;
}
}
// column is ok, set the queen
queens[row]=col;
if(row==size-1) {
// only one thread should print allowed to print at a time
{
// increasing the solution counter is not atomic
#pragma omp critical
nrOfSolutions++;
#ifdef _DEBUG
#pragma omp critical
print(queens);
#endif
}
}
else {
// try to fill next row
for(int i=0; i<size; i++) {
setQueen(queens, row+1, i, id);
}
}
}
void solve() {
int myid=0 ;
#pragma omp parallel
#pragma omp single
{
for(int i=0; i<size; i++) {
/*
#ifdef _OMP //(???)
myid = omp_get_thread_num();
#endif
#ifdef _DEBUG
cout << "ThreadNum: " << myid << endl ;
#endif
*/
// try all positions in first row
// create separate array for each recursion
// started here
#pragma omp task
setQueen(new int[size], 0, i, myid);
}
}
}
int main(int argc, char*argv[]) {
if(argc !=2) {
cerr << "Usage: nq-openmp-taskq boardSize.\n";
return 0;
}
size = atoi(argv[1]);
cout << "Starting OpenMP Task Queue solver for size " << size << "...\n";
double st=omp_get_wtime();
solve();
double en=omp_get_wtime();
printf("Time taken using openmp %lf\n",en-st);
cout << "Number of solutions: " << nrOfSolutions << endl;
return 0;
}