Переместить столбцы матрицы на основе критериев - PullRequest
0 голосов
/ 14 мая 2019

Я пытаюсь в C написать функцию, которая принимает в качестве входных данных матрицу NxM, и, если она находит пустые столбцы, перемещать непустые столбцы влево или вправо от матрицы в зависимости от выбора пользователя. . Пустые столбцы могут быть 1,2 или более.

В качестве примера. Предполагая следующую матрицу:

Матричные элементы:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 0 1 0 8
2| 1 3 0 3 0 1 0 0
3| 3 0 0 0 0 8 0 0
4| 0 0 0 2 6 0 0 4

Как видите, только столбцы 3 и 7 полностью пусты (все 0). Мне нужна функция, которая, если пользователь выбирает l (слева), будет перемещать не пустые столбцы, как они находятся влево. Итак, он вернется:

Матричные элементы:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 1 8 0 0
2| 1 3 3 0 1 0 0 0
3| 3 0 0 0 8 0 0 0
4| 0 0 2 6 0 4 0 0

Если пользователь выберет r (справа), он переместит непустые столбцы, как и вправо. Так что функция вернет:

Матричные элементы:

   1 2 3 4 5 6 7 8
------------------
1| 0 0 1 6 0 0 1 8 
2| 0 0 1 3 3 0 1 0 
3| 0 0 3 0 0 0 8 0 
4| 0 0 0 0 2 6 0 4 

Это мой первый подход:

   void PushL(int (*arr), int rows, int cols){ //function to move columns to left 
    for(int i = 0; i < rows; i++)
        for(int j = 0;j < cols; j++){
                if(arr[i*cols+j] == 0)
                    for(int k = j + 1; k < cols; k++){
                        if(arr[i*cols+k] != 0){
                            arr[i*cols+j] = arr[i*cols+k];
                            arr[i*cols+k] = 0;
                            break;
                         }

                     }

           }

} * * тысяча двадцать-один

Ответы [ 3 ]

1 голос
/ 14 мая 2019

Из-за проблемы, связанной с отсутствием {}, ваша программа не работает, потому что вы рассматриваете только ячейки, имеющие значение 0 или нет, независимо от других ячеек в том же столбце.

Вам необходимо знать, содержит ли все столбец только 0 или нет, прежде чем принять решение о его перемещении или нет

Для этого:

int onlyZero(int (*arr), int col, int rows, int cols)
{
  const int sup = cols*rows;

  for (int i = 0; i != sup; i += cols) {
    if (arr[i + col] != 0)
      return 0;
  }

  return 1;
}

возвращает 1, если столбец col содержит только 0, иначе 0

Чтобы скопировать столбец в другой:

void copyColumn(int (*arr), int fromCol, int toCol, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + toCol] = arr[i + fromCol];
}

и для сброса столбца:

void resetColumn(int (*arr), int col, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + col] = 0;
}

Используя эти функции, даже это не самый быстрый способ:

void PushL(int (*arr), int rows, int cols)
{
  int receiver = 0;

  for (int col = 0; col != cols; ++col) {
    if (!onlyZero(arr, col, rows, cols)) {
      if (receiver != col)
        copyColumn(arr, col, receiver, rows, cols);
      receiver += 1;
    }
  }

  while (receiver != cols)
    resetColumn(arr, receiver++, rows, cols);
}

Добавление

void pr(int (*arr), int rows, int cols)
{
  for (int row = 0; row != rows; ++row) {
    for (int col = 0; col != cols; ++col) {
      printf("%d ", arr[row*cols + col]);
    }
    putchar('\n');
  }
  putchar('\n');
}

int main()
{
  int a[] = { 
    1, 6, 0, 0, 0, 1, 0, 8,
    1, 3, 0, 3, 0, 1, 0, 0,
    3, 0, 0, 0, 0, 8, 0, 0,
    0, 0, 0, 2, 6, 0, 0, 4
  };

  pr(a, 4, 8);
  PushL(a, 4, 8);
  pr(a, 4, 8);
}

Компиляция и исполнение:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall m.c
pi@raspberrypi:/tmp $ ./a.out
1 6 0 0 0 1 0 8 
1 3 0 3 0 1 0 0 
3 0 0 0 0 8 0 0 
0 0 0 2 6 0 0 4 

1 6 0 0 1 8 0 0 
1 3 3 0 1 0 0 0 
3 0 0 0 8 0 0 0 
0 0 2 6 0 4 0 0 

Я разрешаю вам делать PushR, который очень закрыт для PushL

PushR является симметричным PushL :

void PushR(int (*arr), int rows, int cols)
{
  int receiver = cols - 1;

  for (int col = cols-1; col != -1; --col) {
    if (!onlyZero(arr, col, rows, cols)) {
      if (receiver != col)
        copyColumn(arr, col, receiver, rows, cols); 
      receiver -= 1;
    }
  } 

  while (receiver != -1) 
    resetColumn(arr, receiver--, rows, cols);
} 
1 голос
/ 14 мая 2019

Возможно, это не единственная проблема, но в обоих сегментах кода, показанных в исходном сообщении, отсутствуют символы {}, необходимые для предполагаемого намерения. (см. /// here)

void PushR(int (*arr), int rows, int cols){
    for(int i = rows; i > 0; i--)
        for(int j = cols;j > 0; j--){
                if(arr[i*cols+j] == 0)
                    for(int k = j + 1; k < cols; k++){
                        if(arr[i*cols+k] != 0)
                        { /// here
                            arr[i*cols+j] = arr[i*cols+k];
                            arr[i*cols+k] = 0;/// without {} these lines will be executed
                            break;            /// regardless of if evaluation
                        } /// and here
                    }
        }
}

(Отступы в C предназначены только для чтения и не управляют потоком выполнения.)

И чтобы сделать код более читабельным для тех, кто будет его поддерживать в будущем, действительно лучше убрать всю двусмысленность в отношении намерения: (Включить фигурные скобки, если намерение не известно иным образом.)

void PushR(int (*arr), int rows, int cols){
    for(int i = rows; i > 0; i--) {/// added here
        for(int j = cols;j > 0; j--){
            if(arr[i*cols+j] == 0) { /// added here
               for(int k = j + 1; k < cols; k++){
                   if(arr[i*cols+k] != 0) { /// here
                       arr[i*cols+j] = arr[i*cols+k];
                       arr[i*cols+k] = 0;
                       break;
                   } /// and here
                }
            }
        }
     }    
 }
0 голосов
/ 14 мая 2019
void test()
{
    int p[4][9] = {
        1 , 1, 6, 0, 0, 0, 1, 0, 8,
        2 , 1, 3, 0, 3, 0, 1, 0, 0,
        3 , 3, 0, 0, 0, 0, 8, 0, 0,
        4 , 0, 0, 0, 2, 6, 0, 0, 4 };
    int pp[4][9] = {};


    int say = 0;

    for (int i = 0; i < 9; i++)
    { 
        bool ok = false;
        for (int j = 0; j < 4; j++)
        {
            if (p[j][i] != 0)
                ok = true;
        }

        if (ok)
        { 
            for (int j = 0; j < 4; j++)
                pp[j][say] = p[j][i];
            say++;
        }

    }


    for (int j = 0; j < 4; j++)
    for (int i = 0; i < 9; i++)
    {
        printf("%d ", pp[j][i]);
        if (i == 8) printf("\n");
    }

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...