misunderstanding C++ stable_sort - c++

How does the stable_sort from the C++ std function?
Conxtext:
I was trying to solve this leetcode problem.
Long story short, given an array of integers that are at least 0, move the zeros to the end and shift all other numbers accordingly to the left.
Lazy as I am, I tried to do it via stable_sort with a custom compare method, see code below.
class Solution {
public:
vector<int> applyOperations(vector<int>& nums) {
int l=nums.size();
for(int i=1;i<l;i++){
if(nums[i-1]==nums[i]){
nums[i-1]*=2;
nums[i]=0;
}
}
for(int i:nums){
cout<<i<<" ";
}
cout<<"\n";
stable_sort(nums.begin(),nums.end(),co);
return nums;
}
static bool co(const int& x, const int& y){
cout<<x<<" "<<y<<" ";
if(y==0){
cout<<"t\n";
}
else if(x!=0){
cout<<"t\n";
}
else{
cout<<"f\n";
}
return y==0?true:x!=0;
}
};
But the output wasn't what I hoped and expected for the following test case:
[1,2,2,1,1,0]
I tried to do the dumb print debug and this is what I got
1 4 0 2 0 0
4 1 t
0 4 f
0 1 f
0 2 f
0 2 f
0 2 f
0 0 t
0 2 f
2 4 t
0 4 f
0 1 f
0 0 t
0 0 t
The first line, "4 1 t" is technically correct. But I would have expected the call to be made with x=1 and y=4, not the other way around.
What I thought/hoped it would do is to use my custom compare function to determine if the elements are equivalent.
What I now think it does is that, at least for basic type, it uses the basic equality checker, and that for user defined classes it looks for the equality operator of the class.
CPP wasn't much help, unfortunately.
Am I correct in my assumption? Is it compiler defined?
Many thanks!

Related

How to write stack for a recursive function having two recursive functions?

I have been stuck on a problem having two recursive functions in it. I could not understand the mechanism of loop and stack behind it. This are the lines of code of my program.
#include<iostream>
using namespace std;
int test(int num)
{
if (num != 0)
{
num = num - 1;
test(num);
cout << num << " ";
test(num);
}
}
int main()
{
test(3);
}
This is the output of the program
0 1 0 2 0 1 0
Can someone explain me the output of this program using stack?
Unroll the recursion. The output in the rightmost column below matches what you are getting.
executed printed
-------- -------
test(3)
test(2)
test(1)
test(0)
cout << 0 0
test(0)
cout << 1 1
test(1)
test(0)
cout << 0 0
test(0)
cout << 2 2
test(2)
test(1)
test(0)
cout << 0 0
test(0)
cout << 1 1
test(1)
test(0)
cout << 0 0
test(0)
For brevity lets call this function f.
What does this function do? Well, it prints something if its argument is positive and calls itself recursively twice, with the argument decreased by 1. If the argument is zero, the function immediately returns, so the recursion starting from positive arguments will be stopped there. For negative arguments we have an error.
Now, What does it do? It decreases its argument, then calls itself on it, prints it, calls itself again. We can draw a diagram like this:
n: [f(n-1) n-1 f(n-1)]
which means that (neglecting the problem of the number of spaces) it prints whatever f(n-1) prints, then n-1 (and a space), then again f(n-1). The first conclusion: the printout will be symmetric about its central element. And it actually is. If you expand this formula a step further, you'll get this:
n-1: [f(n-2) n-2 f(n-2) n-1 f(n-2) n-2 f(n-2)]
So, in the central position there will always be n-1. Its left-hand and right-hand "neighbour substrings" will be identical. n-2 will be seen in this sequence twice. It's not difficult to see that n-3 will be seen 4 times, etc., till 0 will be seen 2^n times. One can even see that 0 will occupy every second position.
How many numbers will we see? 1 + 2 + ... + 2^n = 2^{n-1} -1. For n=2 this gives 2^3 - 1 = 8 - 1 = 7. That's correct.
What may be the "meaning" of this sequence?
Look (n = 5):
0 1 0 2 0 1 0 3 0 1 0 2 0 1 0 4 0 1 0 2 0 1 0 3 0 1 0 2 0 1 0
Now, take the consequtive integers
1 2 3 4 5 6 7 8 9 10 ... 31
and count the number of times each of them is divisible by 2. Can you see? 1 is not divisible by 2, hence 0 in your sequence. 2 is divisible once, hence 1. 3 is not divisible by 2 - hence 0. 4 is divisible twice, hence 2 on the fourth position. Etc., etc.

C++ Partition a vector of vectors using <algorithm>

Suppose you have a 2D vector defined as follows:
std::vector<vector<int>> v
and which represents a matrix:
1 1 0 1 3
0 4 6 0 1
5 0 0 3 0
6 3 0 2 5
I want to stable-partition (say with predicate el != 0) this matrix, but in all directions. This means that I want to be able to get:
1 1 6 1 3 0 0 0 0 0 1 1 1 3 0 0 1 1 1 3
5 4 0 3 1 1 1 0 1 3 4 6 1 0 0 0 0 4 6 1
6 3 0 2 5 5 4 0 3 1 5 3 0 0 0 0 0 0 5 3
0 0 0 0 0 6 3 6 2 5 6 3 2 5 0 0 6 3 2 5
(down) (up) (right) (left)
For two directions, this can be done very simply by iterating through the outer vector and partitioning the inner vectors (in order or in reverse). However for the other directions I do not know how to go about doing the same.
Is there a way to achieve this using std::stable_partition. Is there maybe another data structure (which supports indexing like vectors) which will allow me to do this more easily?
If I have ti implement this by scratch, is there maybe a standard or recommended way to do it?
You don't need to write your own implementation of the algorithm. Iterators are the customization point when you want to use an existing algorithm for a custom data structure. Unfortunately, writing your own iterator requires quite some boilerplate. I think boost can help, but if you want to stay with what the standard library offers, to my knowledge there is no way around writing it yourself.
The following is to be taken with a grain of salt. I assume all inner vectors are of same size. I do not take into account const_iterators, because you wont need them to use std::stable_partition. I have omitted some member functions that you will have to add yourself. The algorithm requires the iterator to adhere to two named concepts, namely LegacyBidirectionalIterator and ValueSwappable. That being said, here is how you can implement an iterator that enables you to iterate columns of the 2d vector:
#include <iostream>
#include <vector>
struct vector2d_col_iterator {
using container_t = std::vector<std::vector<int>>;
container_t& container;
size_t row;
size_t col;
vector2d_col_iterator& operator++(){
++row;
return *this;
}
bool operator==(const vector2d_col_iterator& other) const {
return col == other.col && row == other.row;
}
bool operator !=(const vector2d_col_iterator& other) const {
return !(*this == other);
}
int& operator*() { return container[row][col]; }
static vector2d_col_iterator begin(container_t& container,int col) {
return {container,0,col};
}
static vector2d_col_iterator end(container_t& container,int col) {
return {container,container.size(),col};
}
};
int main() {
std::vector<std::vector<int>> v{ {1,2,3},{4,5,6}};
auto begin = vector2d_col_iterator::begin(v,1);
auto end = vector2d_col_iterator::end(v,1);
for ( ; begin != end; ++begin) std::cout << *begin << " ";
}
Output:
2 5
Live example
Efficiency is not a really big issue, the matrices will be relatively small. I just want to find the simplest, clearest way of doing this. Preferably without having to write a stable_partition implementation from scratch.
If the matrices are really small (lets say ~20x20 elements) and efficiency is really not a concern, then the simplest is perhaps to use std::stable_partition only on the inner vectors. You can transpose the matrix, call the algorithm in a loop for all inner vectors, transpose again. Done. Thats basically ~10 lines of code. Your choice ;)
With range-v3, you might do:
const std::vector<std::vector<int>> v = /*..*/;
auto is_zero = [](int e){ return e == 0; };
auto right = v;
for (auto& row : right) {
ranges::stable_partition(row | ranges::view::reverse, is_zero);
}
print(right);
auto top = v;
for (std::size_t i = 0; i != v[0].size(); ++i) {
auto col_view = top | ranges::view::transform([i](auto& row)-> int& { return row[i]; });
ranges::stable_partition(col_view, is_zero);
}
print(top);
Demo

Unexpected result C++ [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am creating a Minesweeper game. However, while testing the generating function, It malfunctions almost always (if not always), and I do not understand why.
Here is my code:
#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
struct board {
int width=9, mines=10;
char board[9][9];
/* char board[][]
* -1 = Mine
* 0 = No mines near
* 0+ = x amount of mines are near
*/
};
struct point {
int x,y;
};
board newBoard(){
board board1;
point randPoint;
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++) board1.board[i][j]=0; // Initialize array
}
for(int i=0;i<board1.mines;i++){
randPoint.x=rand()%board1.width, randPoint.y=rand()%board1.width; // Where will the mine go?
if(board1.board[randPoint.x][randPoint.y]!=-1){ // If not already a mine
board1.board[randPoint.x][randPoint.y]=-1; //make a mine
} else i--; //else don't count this
}
for(int i=0;i<board1.width;i++){
for(int j=0;j<board1.width;j++){
if(board1.board[i][j]==-1) { // If mine exists
// The if checks preceding the ++'s are to prevent out of bounds erors
if (j-1>=0) board1.board[i][j-1]++;
if (j+1<board1.width) board1.board[i][j+1]++;
if (i-1>=0) board1.board[i-1][j]++;
if (i+1<board1.width) board1.board[i+1][j]++;
if ((i-1>=0) && (j-1>=0)) board1.board[i-1][j-1]++;
if ((i-1>=0) && (j+1<board1.width))board1.board[i-1][j+1]++;
if ((i+1<board1.width) && (j-1>=0))board1.board[i+1][j-1]++;
if ((i+1<board1.width) && (j+1<board1.width))board1.board[i+1][j+1]++;
}
}
}
return board1;
}
int main() {
board boardGame=newBoard();
printf("- ");
for(int i=0;i<boardGame.width;i++) printf("%i ",i+1);
printf("\n\n");
for(int i=0;i<boardGame.width;i++){
printf("%i. ",i+1);
for(int j=0;j<boardGame.width;j++) if (boardGame.board[i][j]==-1) {
printf(" X");
} else {
printf(" %i", boardGame.board[i][j]);
}
printf("\n");
}
return 0;
}
This produces:
- 1 2 3 4 5 6 7 8 9
1. 0 0 0 0 1 X 1 0 0
2. 1 1 0 0 2 2 2 1 1
3. X 2 1 1 1 X 1 1 X
4. 1 2 X 0 1 1 0 1 1
5. 0 1 1 1 0 0 0 0 0
6. 0 0 0 0 1 1 1 0 0
7. 0 0 1 1 2 X 1 0 0
8. 1 1 2 X 2 1 1 0 0
9. 1 X 2 1 1 0 0 0 0
As you most likely already know, in the game of minesweeper, there is mines (in this case will they will be marked as X), and all nearby grid points are the number of mines near it (if you are still unfamiliar with it this page may of use). As you can see, the numbers at 4,7 and 4,4 are incorrect.
I do not know why this is this way. Could someone aid my understanding in this, and tell my how to to fix this?
Also, I just noticed that this produces the same output every time it is run. Why?
Ioums is correct, you are not checking to see if a cell is a mine before incrementing it. However, with the way that your code is currently set up, this will mean adding a check that the cell does not equal -1 in every single if statement. You should consider creating a function to safely increment a cell if it is within bounds and not a mine, like so:
void safeIncrement(int x, int y, board& b)
{
if(x >= 0 && y >= 0 && x < b.width && y < b.width && b.board[x][y] != -1)
{
b.board[x][y]++;
}
}
This means that you can replace your if statements with:
safeIncrement(i-1,j,board1);
safeIncrement(i-1,j-1,board1);
safeIncrement(i-1,j+1,board1);
safeIncrement(i,j-1,board1);
safeIncrement(i,j+1,board1);
safeIncrement(i+1,j,board1);
safeIncrement(i+1,j-1,board1);
safeIncrement(i+1,j+1,board1);
Which is much more readable in my opinion. Additionally, since the function doesn't increment the cell if it is a mine, you could also replace the if statements with the following code!
for(int a=-1; a<=1; a++)
{
for(int b=-1; b<=1; b++)
{
safeIncrement(i+a,j+b, board1);
}
}
The problem happens when 2 mines are close together: when you're adding to the mine count, you don't check if that square has a mine.
Suppose you get a mine on (0, 0) and another on (0, 1). When you're adding to the mine count around (0, 0), you accidentally also add to the mine in (0, 1), changing it from -1 to 0. It also makes the second mine being processed disappear.
I suggest using another number to signal a mine, like -999, and check if the number is negative when looking for them. It's easier than adding another condition for all if clauses you already have.

CUSP sparse library giving strange results

I'm trying to do the following in CUSP:
A=[
1,1,0,0;
2,2,2,0;
0,3,3,3;
0,0,4,4];
B=[1,1,1,1]';
disp(mldivide(A,B));
which is
X=[0.9167,0.0833,-0.5000,0.7500]
On the other hand I get a strange answer from CUSP
#include <cusp/dia_matrix.h>
#include <cusp/krylov/cg.h>
#include <cusp/print.h>
int main()
{
cusp::dia_matrix<int,float,cusp::host_memory> A(4,4,10,3);
A.diagonal_offsets[0] = -1;
A.diagonal_offsets[1] = 0;
A.diagonal_offsets[2] = 1;
for (int i = 0;i <3;i++)
{
for (int q = 0 ;q < A.num_cols;q++)
{
A.values(q,i)=q+1;
}
}
//copy
cusp::dia_matrix<int,float,cusp::device_memory> AA = A;
cusp::array1d<float,cusp::device_memory> BB(A.num_rows,1);
cusp::array1d<float,cusp::device_memory> XX(A.num_rows,0);
cusp::print(AA);
cusp::print(XX);
cusp::print(BB);
cusp::krylov::cg(AA,XX,BB);\
cusp::print(XX);
return 0;
}
The result looks like
sparse matrix <4, 4> with 10 entries
0 0 1
0 1 1
1 0 2
1 1 2
1 2 2
2 1 3
2 2 3
2 3 3
3 2 4
3 3 4
array1d <4>
0
0
0
0
array1d <4>
1
1
1
1
array1d <4>
-39.9938
-53.436
87.9025
-30.1429
The last one doesn't look quite right. Anybody know what I'm doing wrong? Am I using the code wrong or are we supposed to have a really good guessed solution + use a preconditioner?
The conjugate gradient method is only valid for use in symmetric positive definite matrices. Your matrix isn't symmetric. That is why it isn't (and cannot) producing a valid solution. Either use an appropriate, well conditioned SPD matrix, or use a different numerical method.

Why does it cout in something that we doesn't cin in arrays?

When the following program is fead the following input (reading from cin):
1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
The output is surprising:
1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int main()
{
int arey[3][3];
int i,j;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cin>>arey[j][i];
}
}
arey[0][0]=1;
arey[3][3]=1;
i=0,j=0;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cout<<arey[j][i];
}
}
return 0;
}
Can someone explain what I should change to get the same output as the input?
Is the matrix 3x3 or 4x4?
you created 3x3 but the loops run for 4 elements and you also update [3][3]
Basically your indexes overflow and you overwrite a different cell in the matrix.
Update: cheecked your input, use: int arey[4][4];
Arrays use 0 based indices, so the valid range of indices for your
int arey[3][3];
are 0 <= i < 3 and 0 <= j < 3
So you need to change the condition in your for loops to be strictly < instead of <=
I really don't think I understand your question, but this is wrong:
int arey[3][3];
...
for(j=0;j<=3;j++) // <= invalid
...
array[3][3]=1; // out of bounds
arey is a 3*3 array. You can't access arey[3][?], that's out of bounds. The only valid indices are 0..2.
Once you've written past the bounds of your array, your program behavior becomes undefined.