qsort not working - messing up array completely - c++

So, I have a struct, consisting of 3 integers. This struct represents one "row" of my "table". Table is basically array of rows, called "v" Because of the task I have, I need to use this format instead of for example 2d array and these things. For now, I need to "lexicographically sort my rows" according to x,y and z. The problem is with the qsort function - it somehow messes up my whole array "v" that becomes useless. I don`t now what is the reason for it. The compare function compares the rows according to x, than according to y and than z (normal lexicographical sorting I think). Function printing just prints the table.
#include <iostream>
#include <stdlib.h>
using namespace std;
struct row {
int x, y, z;
};
int compar(const void* p1, const void* p2){
if(((row*)p1)->x < ((row*)p2)->x){
return -1;
}
if(((row*)p1)->x = ((row*)p2)->x){
if(((row*)p1)->y < ((row*)p2)->y){
return -1;
}
if(((row*)p1)->y = ((row*)p2)->y){
if(((row*)p1)->z < ((row*)p2)->z){
return -1;
}
if(((row*)p1)->z = ((row*)p2)->z){
return 0;
}
if(((row*)p1)->z > ((row*)p2)->z){
return 1;
}
}
if(((row*)p1)->y > ((row*)p2)->y){
return 1;
}
}
if(((row*)p1)->x > ((row*)p2)->x){
return 1;
}
}
void printing(row v[], int p){
cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endl;
for (int i = 0; i < p; i++){
cout << v[i].x << " " << v[i].y<< ' ' << v[i].z << endl;
}
cout << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << endl;
}
int main(void){
int numOfRows;
cin >> numOfRows; //format of input needs this
row v[numOfRows];
for (int i = 0; i < numOfRows; i++) {
cin >> v[i].x >> v[i].y >> v[i].z;
}
qsort(v,numOfRows,sizeof(row),compar);
printing(v,numOfRows);
}
now I am posting inputs with outputs and you can clearly see, that some rows were duplicated in sorting process and some of them are missing completely.
3
1 2 3
1 4 5
1 2 4
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1 2 3
1 2 4
1 2 4
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
next input and output is:
4
100 100 100
100 100 100
100 99 99
99 99 100
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
99 99 99
99 99 99
99 99 99
99 99 100
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
How it should apparently look instead is for example:
3
1 2 3
1 4 5
1 2 4
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
1 2 3
1 2 4
1 4 5
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
This would be the correct output of my qsort. Any help would be gladly appreciated, as I have absolutely no idea why this happens. I have been trying to solve this for the whole afternoon and I am out of ideas. Thanks a lot

A lot of your comparisons have = instead of ==, and that will lead to values being copied to places where they shouldn't be. If you set the warning level on your compiler high enough it should warn you about this.

The function compar does not have a return value at the end. It leads to undefined behavior.
You can simplify it to:
int compar(const void* p1, const void* p2)
{
row const* row1 = (row const*)p1;
row const* row2 = (row const*)p2;
if ( row1->x != row2->x )
{
return (row1->x - row2->x);
}
if ( row1->y != row2->y )
{
return (row1->y - row2->y);
}
return (row1->z - row2->z);
}

Related

Why is the code after my for loop being ignored?

I don't think you'll need to know the context of the problem to answer this question, but I'll give it just in case.
-In the past N weeks, we've measured the amount of rainfall every day, and noted it down for each day of the week. Return the number of the first week of the two week period where there were the most days without rain.
The code gives no warnings or errors, and if I try to print dryestweeks inside the second for loop, then it returns the correct answer. However, all of the code after the second for loop seems to be getting ignored, and I'm getting Process returned -1073741819 (0xC0000005). The issue has to lie in the 2nd for loop, because if I comment it out then both "test2" and dryestweeks get printed, and the program returns 0.
#include <iostream>
#include <vector>
#include <bits/stdc++.h>
using namespace std;
int main() {
int weeks;
cin >> weeks;
vector<int> v[weeks];
for (int i = 0;i < weeks; i++) {
int a, b, c, d, e, f, g;
cin >> a >> b >> c >> d >> e >> f >> g;
v[i].push_back(a);
v[i].push_back(b);
v[i].push_back(c);
v[i].push_back(d);
v[i].push_back(e);
v[i].push_back(f);
v[i].push_back(g);
}
int mostdrydays = 0;
int dryestweeks = 0;
for (int i = 0; i < weeks; i++) {
int weeklydrydays = count(v[i].begin(), v[i].end(), 0);
int nextweekdrydays = count(v[i+1].begin(), v[i+1].end(), 0);
int biweeklydrydays=weeklydrydays+nextweekdrydays;
if (biweeklydrydays > mostdrydays) {
mostdrydays = biweeklydrydays;
dryestweeks = i + 1;
}
}
cout << "test2" << endl;
cout << dryestweeks << endl;
return 0;
}
An example of an input would be:
6
5 10 15 20 25 30 35
0 2 0 0 0 0 0
0 0 0 1 0 3 0
0 1 2 3 4 5 6
5 1 0 0 2 1 0
0 0 0 0 0 0 0
The program should print "2" with the above input.
The second loop has an overflow.
You first defined v[weeks] and then the second loop goes from [0, weeks[ but you are retrieving the next week with v[i + 1]. I don't know exactly what are you are trying to achieve, but if you do
for(int i = 0; i < weeks - 1; i++)
{
...
}
it executes properly.
For the given example of input, in the last iteration (i = 5) of the second loop, index i + 1(=6) will be out of the bound for v[i + 1] (legal indices for v will be from 0 to 5).
The second loop is iterating one more time than required.

C++ Having an issue with filling an array

I'm having an issue with my C++ code that involves receiving input from the user and filling an array based on that input. For my function fillArray(), I need a way to read all inputs from one line and to fill an array with those inputs until the user inputs -1 at the end, something other than a positive integer, or exceeds the threshold of 20 elements.
For example, if I input
1 2 3 4 5 6 -1 on one line, I want the displayArray() function to output 1 2 3 4 5 6, or if i write 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21, I want displayArray() to output 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20.
It seems that whenever I input -1 at the end, displayArray() outputs something like
1 2 3 4 5 6 94837 or some arbitrarily big number. If somebody could help me out with this, I'd appreciate it, here's my code:
#include <iostream>
using namespace std;
const int CAPACITY = 20;
void displayArray(int array[], int numElements)
{
for (int i = 0; i < numElements; i++)
cout << array[i] << " ";
cout << endl;
}
void fillArray(int array[], int& numElements)
{
int arrayPosition = 0;
int testArrayPosition = 0;
int testArray[CAPACITY];
bool continueReading = true;
cout << "Enter a list of up to 20 integers or -1 to end the list";
do
{
cin >> valueEntered;
if (valueEntered == -1)
{
continueReading = false;
} else if (valueEntered != -1) {
array[arrayPosition] = valueEntered;
arrayPosition++;
}
} while ((continueReading==true) || (arrayPosition >= CAPACITY));
numElements = (arrayPosition+1);
}
int main()
{
int array[CAPACITY];
int numArrayElements = 0;
fillArray(array, numArrayElements);
displayArray(array, numArrayElements);
cout << "NumArrayElements: " << numArrayElements << endl;
}
The code you posted does not compile. You refer in several places to a variable valueEntered without ever having declared it.
Also, the following construct does not make sense:
if (valueEntered == -1)
{
[...]
}
else if (valueEntered != -1)
{
[...]
Since the condition expression of the second if statement is the exact negation of the condition expression of the first statement, the second if statement is superfluous and can be removed, like this:
if (valueEntered == -1)
{
[...]
}
else
{
[...]
However, since you stated in your question that anything else than a positive integer (not just -1) should cause your program to end, you will want to change that part of your program to the following:
if (valueEntered <= 0)
{
continueReading = false;
}
else
{
array[arrayPosition] = valueEntered;
arrayPosition++;
}
Also, as has already been stated by someone else in the comments section, the line
while ((continueReading==true) || (arrayPosition >= CAPACITY));
should be changed to
while ( continueReading && arrayPosition < CAPACITY )
and the line
numElements = (arrayPosition+1);
should be changed to
numElements = arrayPosition;

Pattern Printing-Where am I going wrong in this C++ code?

I wrote a program to print a N x N square pattern with alternate 0's and 1's. For eg. A 5 x 5 square would looks like this:
I used the following code-
#include<iostream.h>
int main()
{
int i, n;
cin >> n; //number of rows (and columns) in the n x n matrix
for(i = 1; i <= n*n; i++)
{
cout << " " << i%2;
if(i%n == 0)
cout << "\n";
}
fflush(stdin);
getchar();
return 0;
}
This code works fine for odd numbers but for even numbers it prints the same thing in each new line and not alternate pattern.For 4 it prints this-
Where am I going wrong?
In my opinion the best way to iterate over matrix is using loop in another loop.
I think this code will be helpful for you:
for(i = 0; i < n; i++) {
for (j = 1; j <= n; j++) {
cout<<" "<< (j + i) % 2;
}
cout<<"\n";
}
where n is number of rows, i and j are ints.
Try to understand why and how it works.
If you're a beginner programmer, then I suggest (no offence) not trying to be too clever with your methodology; the main reason why your code is not working is (apart from various syntax errors) a logic error - as pointed out by blauerschluessel.
Just use two loops, one for rows and one for columns:
for (int row = 1; row <= n; row++)
{
for (int col = 0; col < n; col++)
cout << " " << ((row % 2) ^ (col % 2));
cout << "\n";
}
EDIT: since you wanted a one-loop solution, a good way to do so would be to set a flip flag which handles the difference between even and odd n:
bool flip = false;
int nsq = n * n;
for (int i = 1; i <= nsq; i++)
{
cout << " " << (flip ^ (i % 2));
if (i % n == 0) {
if (n % 2 == 0) flip = !flip;
cout << "\n";
}
}
The reason that it isn't working and creating is because of your logic. To fix this you need to change what the code does. The easiest way to handle that is to think of what it does and compare that to what you want it to do. This sounds like it is for an assignment so we could give you the answer but then you would get nothing from our help so I've writen this answer to guide you to the logic of solving it yourself.
Lets start with what it does.
Currently it is going to print 0 or 1 n*n times. You have a counter named i that will increment every time starting from 0 and going to (n*n)-1. If you were to print this number i you would get the following table for n=5
1 2 3 4 5
6 7 8 9 10
11 12 13 14 15
16 17 18 19 20
21 22 23 24 25
Now you currently check if the value i is odd or even i%2 and this makes the value 0 or 1. Giving you the following table
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
0 1 0 1 0
1 0 1 0 1
Now in the case of n=4 your counter i would print out to give you a table
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Now if you print out the odd or even pattern you get
1 0 1 0
1 0 1 0
1 0 1 0
1 0 1 0
This pattern diffrence is because of the changing pattern of printed numbers due to the shape of the square or more accurately matrix you are printing. To fix this you need to adjust the logic of how you determine which number to print because it will only work for matrixes that have odd widths.
You just need to add one more parameter to print the value. Below mentioned code has the updated for loop which you are using:
int num = 0;
for(i = 1; i <= n*n; i++)
{
num = !num;
std::cout << " " << num;
if(i%n == 0) {
std::cout << "\n";
num = n%2 ? num : !num;
}
}
The complete compiled code :
#include <iostream>
#include <stdio.h>
int main()
{
int i, n, num = 0;
std::cin >> n; //number of rows (and columns) in the n x n matrix
for(i = 1; i <= n*n; i++)
{
num = !num;
std::cout << " " << num;
if(i%n == 0) {
std::cout << "\n";
num = n%2 ? num : !num;
}
}
fflush(stdin);
getchar();
return 0;
}

Algorithm for Combinations of given numbers with repetition? C++

So I N - numbers I have to input, and I got M - numbers of places for those numbers and I need to find all combinations with repetition of given numbers.
Here is example:
Let's say that N is 3(I Have to input 3 numbers), and M is 4.
For example let's input numbers: 6 11 and 533.
This should be result
6,6,6,6
6,6,6,11
6,6,6,533
6,6,11,6
...
533,533,533,533
I know how to do that manualy when I know how much is N and M:
In example where N is 3 and M is 4:
int main()
{
int N = 3;
int M = 4;
int *numbers = new int[N + 1];
for (int i = 0; i < N; i++)
cin >> numbers[i];
for (int a = 0; a < N; a++)
for (int b = 0; b < N; b++)
for (int c = 0; c < N; c++)
for (int d = 0; d < N; d++)
{
cout << numbers[a] << " " << numbers[b] << " " << numbers[c] << " " << numbers[d] << endl;
}
return 0;
}
But how can I make algorithm so I can enter N and M via std::cin and I get correct resut?
Thanks.
First one short tip: don't use "new" or C-style arrays in C++ when we have RAII and much faster data structures.
For the solution to your problem I would suggest making separate function with recursion. You said you know how to do it manually so the first step in making it into algorithm is to tear down you manual solution step by step. For this problem when you solve it by hand you basically start with array of all first numbers and then for last position you just loop through available numbers. Then you go to the second last position and again loop through available numbers just now with the difference that for every number there you must also repeat the last spot number loop. Here is the recursion. For every "n"th position you must loop through available numbers and for every call the same function for "n+1"th number.
Here is a simplified solution, leaving out the input handling and exact print to keep code shorter and more focused on the problem:
#include <vector>
#include <iostream>
void printCombinations(const std::vector<int>& numbers, unsigned size, std::vector<int>& line) {
for (unsigned i = 0; i < numbers.size(); i++) {
line.push_back(numbers[i]);
if (size <= 1) { // Condition that prevents infinite loop in recursion
for (const auto& j : line)
std::cout << j << ","; // Simplified print to keep code shorter
std::cout << std::endl;
line.erase(line.end() - 1);
} else {
printCombinations(numbers, size - 1, line); // Recursion happens here
line.erase(line.end() - 1);
}
}
}
int main() {
std::vector<int> numbers = {6, 11, 533};
unsigned size = 4;
std::vector<int> line;
printCombinations(numbers, size, line);
return 0;
}
If you have any questions feel free to ask.
Totally there is no need for recursion here. This is a typical job for dynamic programming. Just get the first solution right for n = 1 (1 slot is available) which means the answer is [[6],[11],[533]] and then move on one by one by relying on the one previously memoized solution.
Sorry that i am not fluent in C, yet in JS this is the solution. I hope it helps.
function combosOfN(a,n){
var res = {};
for(var i = 1; i <= n; i++) res[i] = res[i-1] ? res[i-1].reduce((r,e) => r.concat(a.map(n => e.concat(n))),[])
: a.map(e => [e]);
return res[n];
}
var arr = [6,11,533],
n = 4;
console.log(JSON.stringify(combosOfN(arr,n)));
Normally the easiest way to do dynamic nested for loops is to create your own stack and use recursion.
#include <iostream>
#include <vector>
void printCombinations(int sampleCount, const std::vector<int>& options, std::vector<int>& numbersToPrint) {
if (numbersToPrint.size() == sampleCount) {
// got all the numbers we need, print them.
for (int number : numbersToPrint) {
std::cout << number << " ";
}
std::cout << "\n";
}
else {
// Add a new number, iterate over all possibilities
numbersToPrint.push_back(0);
for (int number : options) {
numbersToPrint.back() = number;
printCombinations(sampleCount, options, numbersToPrint);
}
numbersToPrint.pop_back();
}
}
void printCombinations(int sampleCount, const std::vector<int>& options) {
std::vector<int> stack;
printCombinations(sampleCount, options, stack);
}
int main()
{
printCombinations(3, {1,2,3});
}
output
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
Here is an algorithm to solve this, that does't use recursion.
Let's say n=2 and m=3. Consider the following sequence that corresponds to these values:
000
001
010
011
100
101
110
111
The meaning of this is that when you see a 0 you take the first number, and when you see a 1 you take the second number. So given the input numbers [5, 7], then 000 = 555, 001=557, 010=575 etc.
The sequence above looks identical to representing numbers from 0 to 7 in base 2. Basically, if you go from 0 to 7 and represent the numbers in base 2, you have the sequence above.
If you take n=3, m=4 then you need to work in base 3:
0000
0001
0002
0010
0011
0012
....
So you go over all the numbers from 0 to 63 (4^3-1), represent them in base 3 and follow the coding: 0 = first number, 1 = second number, 2 = third number and 3 = fourth number.
For the general case, you go from 0 to M^N-1, represent each number in base N, and apply the coding 0 = first number, etc.
Here is some sample code:
#include <stdio.h>
#include <math.h>
void convert_to_base(int number, char result[], int base, int number_of_digits) {
for (int i = number_of_digits - 1; i >= 0; i--) {
int remainder = number % base;
number = number / base;
result[i] = '0' + remainder;
}
}
int main() {
int n = 2, m = 3;
int num = pow(n, m) - 1;
for (int i = 0; i <= num; i++) {
char str[33];
convert_to_base(i, str, n, m);
printf("%s\n", str);
}
return 0;
}
Output:
000
001
010
011
100
101
110
111

Permutations &/ Combinations using c++

I need a different version of permutations for my code. I could able to achieve what I want but it is not generic enough. my algorithm keeps going bigger along with my requirements. But that should not be.
This is not a home work for any one, I need it for one my critical projects, wondering if any pre-defined algorithms available from boost or any other.
Below is the standard version of next_permutation using c++.
// next_permutation example
#include <iostream> // std::cout
#include <algorithm> // std::next_permutation
int main ()
{
int myints[] = {1,2,3};
do
{
std::cout << myints[0] << ' ' << myints[1] << ' ' << myints[2] << '\n';
} while ( std::next_permutation(myints,myints+3) );
return 0;
}
That gives below output :
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
But my requirement is :- Let's say I have 1 to 9 numbers :
1,2,3,4,5,6,7,8,9
And I need a variable length of permutations and in only ASCENDING order and with out DUPLICATES.
Let's say i need 3 digit length of permutations then i need output as below.
123
124
125
.
.
.
128
129
134 // After 129 next one should be exactly 134
135 // ascending order mandatory
136
.
.
.
148
149
156 // exactly 156 after 149, ascending order mandatory
.
.
.
489 // exactly 567 after 489, because after 3rd digit 9, 2nd digit
567 // will be increased to 49? , so there is no possibility for
. // 3rd digit, so first digit gets incremented to 5 then 6 then
. // 7, in ascending order.
.
.
.
789 // and this should be the last set I need.
My list may contain upto couple of hundred's of numbers and variable length can be 1 to up to Size of the list.
My own algorithm is working for specific variable length, and a specific size, when they both changes, i need to write huge code. so, looking for a generic one.
I am not even sure if this is called as Permutations or there is a different name available for this kind of math/logic.
Thanks in advance.
musk's
Formally, you want to generate all m-combinations of the set [0;n-1].
#include <iostream>
#include <vector>
bool first_combination (std::vector<int> &v, int m, int n)
{
if ((m < 0) || (m > n)) {
return false;
}
v.clear ();
v.resize (m);
for (int i = 0; i < m; i++) {
v[i] = i;
}
return true;
}
bool next_combination (std::vector<int> &v, int m, int n)
{
for (int i = m - 1; i >= 0; i--) {
if (v[i] + m - i < n) {
v[i]++;
for (int j = i + 1; j < m; j++) {
v[j] = v[j - 1] + 1;
}
return true;
}
}
return false;
}
void print_combination (const std::vector<int> &v)
{
for (size_t i = 0; i < v.size(); i++) {
std::cout << v[i] << ' ';
}
std::cout << '\n';
}
int main ()
{
const int m = 3;
const int n = 5;
std::vector<int> v;
if (first_combination (v, m, n)) {
do {
print_combination (v);
} while (next_combination (v, m, n));
}
}
You can use this code and the linked article as inspiration.
This task can be done with a simple iterative algorithm. Just increment the first element that can be incremented and rescale the elements before it until there is no element to be incremented.
int a[] = {0,1,2,3,4,5,6,7,8,9}; // elements: must be ascending in this case
int n = sizeof(a)/sizeof(int);
int digits = 7; // number of elements you want to choose
vector<int> indexes; // creating the first combination
for ( int i=digits-1;i>=0;--i ){
indexes.push_back(i);
}
while (1){
/// printing the current combination
for ( int i=indexes.size()-1;i>=0;--i ){
cout << a[indexes[i]] ;
} cout << endl;
///
int i = 0;
while ( i < indexes.size() && indexes[i] == n-1-i ) // finding the first element
++i; // that can be incremented
if ( i==indexes.size() ) // if no element can be incremented, we are done
break;
indexes[i]++; // increment the first element
for ( int j=0;j<i;++j ){ // rescale elements before it to first combination
indexes[j] = indexes[i]+(i-j);
}
}
Output:
0123456
0123457
0123458
0123459
0123467
0123468
0123469
0123478
0123479
0123489
0123567
0123568
0123569
0123578
0123579
0123589
0123678
0123679
0123689
0123789
0124567
0124568
0124569
0124578
0124579
0124589
0124678
0124679
0124689
0124789
0125678
0125679
0125689
0125789
0126789
0134567
0134568
0134569
0134578
0134579
0134589
0134678
0134679
0134689
0134789
0135678
0135679
0135689
0135789
0136789
0145678
0145679
0145689
0145789
0146789
0156789
0234567
0234568
0234569
0234578
0234579
0234589
0234678
0234679
0234689
0234789
0235678
0235679
0235689
0235789
0236789
0245678
0245679
0245689
0245789
0246789
0256789
0345678
0345679
0345689
0345789
0346789
0356789
0456789
1234567
1234568
1234569
1234578
1234579
1234589
1234678
1234679
1234689
1234789
1235678
1235679
1235689
1235789
1236789
1245678
1245679
1245689
1245789
1246789
1256789
1345678
1345679
1345689
1345789
1346789
1356789
1456789
2345678
2345679
2345689
2345789
2346789
2356789
2456789
3456789