2
votes

I have a matrix that I am trying to "count" through by shifting the first row to the left n number of times until it is in its original position, at which point I would shift the second row to the left once, then go through the entire first row again, shift the second row once, so on and so forth until the second row is in its original position, at which point the third row would shift once and we start all over again.

For example:

0 1 2     1 2 0     2 0 1     0 1 2     1 2 0     2 0 1   a few     0 1 2     1 2 0
0 1 2 ==> 0 1 2 ==> 0 1 2 ==> 1 2 0 ==> 1 2 0 ==> 1 2 0 ==> ==> ==> 0 1 2 ==> 0 1 2 ... ... ...
0 1 2     0 1 2     0 1 2     0 1 2     0 1 2     0 1 2    more     1 2 0     1 2 0

all the way until every possible combination has been reached. In an MxN matrix this should give me N^M possibilities. The actual matrix I am working with is much larger than this one so I am trying to avoid 250+ nested loops.

I already have the shift method:

static inline void shift(uint8_t *row){ //a row from a 2D Array
  int a, temp;
  int b = sizeof(row);
  temp = row[0];
  for(a = 0; a < b; a++){
    channel[a] = channel[a+1];
  }
  channel[b] = temp;
}

Any help would be greatly appreciated.

2
This line of code: int b = sizeof(row); is not correct. row is a pointer, you cannot know its size. You must pass the size of the row as a separate parameter to the function. - Luca Polito
@LucaPolito nit. You can know the size of row (it is the size of a pointer), but it is unrelated to the number of elements in the row. - William Pursell
@WilliamPursell well yes, by "size of the pointer" I meant "size of what the pointer points to". The former phrase is more "direct", I think. - Luca Polito

2 Answers

1
votes

Really nice question, I appreciate you for this. I am doing the question in very basic way for better understanding, must read all line comments to understand the program. I am tested this on TurboC by printing matrix after each shift and its working according to me. If you want some improvement or it require some change to reach your requirement then you may try or just give a comment.All the best.

#include<stdio.h>

#define MAX 50

void shift(int *rowToShift, int size){
//To circular shift the row
 int i,tmp = rowToShift[0];
 for(i=0;i<size-1;i++){
    rowToShift[i] = rowToShift[i+1];
 }
 rowToShift[size-1] = tmp;
}

void main(){

 //I am just initilizing matrix with your initial data, I tested on this
 int mat[MAX][MAX] = {{0,1,2},{0,1,2},{0,1,2}};
 int row=3,col=3;//you may get it from user

 // We keep it always on row we shifting
 int currentRow=0;

 /*This tracker helps to track which row incremented
 how many times*/
 int shiftTracker[MAX];
 while(currentRow < row){

  //Shift current row to 1 left, (circular left as you ask)
  shift(mat[currentRow],col);

  shiftTracker[currentRow]++;

  if(shiftTracker[currentRow] == row){
   /*if current row shift is completed, means
     Now again in original condition*/

   shiftTracker[currentRow] = 0; //Reset traker for current row

   currentRow++;//Moving to Next row

   if(currentRow == row){
   //if all rows are completed
    break;
   }
  }
  else if(shiftTracker[currentRow] < row && currentRow != 0){
   //if all rows not completed and currentRow not on 0
   currentRow = 0;
  }
 }
}
1
votes

Your shift() function can be improved this way:

static void shift(uint8_t* row, size_t row_size) {
  uint8_t temp = row[0];
  for (size_t i = 0; i < row_size - 1; i += 1) {
    row[i] = row[i + 1];
  }
  row[row_size - 1] = temp;
}
// P.S.: row_size must be at least 1, or the function will break