0

I am created a double for loop in Rcpp to move up one cell all 1's in a column that has 5 in the next available cell. When I compile the code I don't get any error but the code does move 1's in the matrix, it just returns the same matrix. Let's take an original matrix, say named t:

5    1    1    1    1
1    5    5    5    1
5    5    1    5    5
5    0    0    5    1
5    5    0    1    1

after running the code up_rcpp(t,5,5), I should get the following results

    1    5    1    1    1
    5    5    1    5    1
    5    5    5    5    1
    5    0    0    5    5
    5    1    0    1    1

Below is my rcpp code:

 #include <Rcpp.h>

using namespace Rcpp;

//[[Rcpp::export]]

Rcpp::NumericMatrix up_rcpp(Rcpp::NumericMatrix main, int r, int c) {
  

 Rcpp::NumericMatrix t = clone(main);

  
  for (int j=0; j <= c-1; ++j) {
for (int i=0; i <= r-2; ++i){
  
  if ((t(i,j) == 5) & (t(i+1, j) == 1))
  {
    
    main(i, j)  = 1;
    main(i + 1, j) = 5;
  }
}

for (int i= r-1; i == r-1; ++i){
  if ((t(i, j) == 5) & (t(1, j) == 1))
  {
   
    main(i, j) = 1;
    main(1, j) = 5;
  }
}
  }

  return main;

}
KEN
  • 55
  • 5
  • Did you compile your Rcpp code? I get a different matrix, but not the desired answer when I run your code. – Brian Montgomery Oct 15 '21 at 02:00
  • 'for (int i=0; i < r-2; ++i){' should be 'for (int i=0; i <= r-2; ++i){' I'm still not getting the answer you said you want, but I'm not clear on what is supposed to happen. Can there be multiple swaps in the same column? – Brian Montgomery Oct 15 '21 at 03:12
  • @BrianMontgomery yes, there can be multiple swaps in the same column. So taking an individual column, if the value 1 exist and the up cell has the value 5, we can swap the two cells. For 1's in the matrix[1,1] can be swap with the cell in the matrix[1,5] if the value in matrix[1,5] is 5. – KEN Oct 15 '21 at 14:47
  • You need: Rcpp::NumericMatrix t = clone(main); otherwise t and main share the same address and a change in main will affect t. – Brian Montgomery Oct 15 '21 at 19:32

1 Answers1

1

Maybe I'm a bit paranoid when I pass values to Rcpp, but I never allow my function to change what I pass either. But the clone(main) is necessary here to avoid changes to main changing t. The last piece was to change the 1 indicies to 0 for the top row.

#include <Rcpp.h>

using namespace Rcpp;

//[[Rcpp::export]]

Rcpp::NumericMatrix up_rcpp(Rcpp::NumericMatrix main, int r, int c) {
  
  
  Rcpp::NumericMatrix ans = clone(main);
  Rcpp::NumericMatrix t = clone(main);

  
  for (int j=0; j <= c-1; ++j) {
    for (int i=0; i <= r-2; ++i){
 
      if ((t(i,j) == 5) && (t(i+1, j) == 1))
      {
        
        ans(i, j)  = 1;
        ans(i + 1, j) = 5;
        
      }
    }
    for (int i= r-1; i <= r-1; ++i){
      if ((t(i, j) == 5) && (t(0, j) == 1))
      {
        ans(i, j) = 1;
        ans(0, j) = 5;
      }
    }
  }
  
  return ans;
  
}

Which gives:

     [,1] [,2] [,3] [,4] [,5]
[1,]    1    5    1    1    1
[2,]    5    5    1    5    1
[3,]    5    5    5    5    1
[4,]    5    0    0    1    5
[5,]    5    1    0    5    1

This is different than your solution in column 4, but the way I understand the logic, this is correct.

Brian Montgomery
  • 2,244
  • 5
  • 15
  • yes, your result is correct. Just a follow-up question. What is the difference between && and &. Thank you. – KEN Oct 16 '21 at 04:12
  • In C++ there is a good explanation here: https://stackoverflow.com/questions/34492501/difference-between-and-or-and – Brian Montgomery Oct 16 '21 at 04:41
  • Hey @KEN, thanks for acknowledging that my response was correct. I was worried I didn't understand completely. Please upvote/accept my response. It took a fair amount of time to track down multiple bugs and deal with an incorrect desired result. – Brian Montgomery Oct 19 '21 at 01:14