Search code examples
rrcpprcpp11

Trying to move numbers in NumericMatrix


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;

}

Solution

  • 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.