【问题标题】:Is there a simpler way to do this check?有没有更简单的方法来做这个检查?
【发布时间】:2020-12-21 19:18:35
【问题描述】:

我必须用随机数01 填充一个矩阵,但如果一个单元格包含1,则它周围的其他8 个必须为0。作为初学者,我尝试在此实现我的代码方式:

for (int i = 0; i < 5; i++) {
    for (int j = 0; j < 5; j++) {
        a[i][j] = rand() % 2;
        if (a[i][j] == 1) {
            a[i-1][j-1] = 0; 
            a[i-1][j]   = 0; 
            a[i-1][j+1] = 0;
            a[i][j-1]   = 0; 
            a[i][j+1]   = 0;
            a[i+1][j+1] = 0; 
            a[i+1][j]   = 0; 
            a[i+1][j+1] = 0;
        }
    }
}

当然,我确信有一种更简单的方法可以编写此代码。你能帮助我吗?提前致谢!

【问题讨论】:

  • 我不认为您所做的事情是不合理的,只是当在角落或边缘生成1 时,它会超出数组的边界,这将是相当频繁的。你需要避免这种情况。
  • @JohnBollinger 我知道我的代码有效,但我认为它是多余的。我确信有一种更简单、更清洁的方法可以做到这一点。这是我的问题,但无论如何我会解决你向我报告的错误,谢谢!
  • 0+没有理由
  • 假设 2 个相邻单元格包含 1?哪个决定?如果你用0 覆盖其中一个,那么它的 个邻居呢?我认为你只能通过两阶段的过程来解决这个问题,从第一个数组创建第二个数组。
  • 如果代码有效并且您正在寻找改进它的建议,Code Review 是合适的地方。但请先查看codereview.meta.stackexchange.com/questions/5777/…

标签: c matrix random coding-style code-cleanup


【解决方案1】:

您可能应该分两步完成,否则,您可以在之前擦除的单元格上再次写入 1。此外,您必须避免在矩阵之外写入。这是一个例子:

int main()
{
    // First fills the matrix :
    int a[5][5] = {0};
    printf("Random Matrix :\n");
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 5; j++){
            a[i][j] = rand() % 2;
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    // Next filters it :
    printf("---------\nFiltered Matrix :\n");
    for (int i = 0; i < 5; i++){
        for (int j = 0; j < 5; j++){
            if (a[i][j] == 1) {
                if (i > 0) {
                    a[i-1][j]              = 0; 
                    if (j > 0) a[i-1][j-1] = 0;
                    if (j < 4) a[i-1][j+1] = 0;
                }
                if (i < 4) {
                    a[i+1][j]              = 0; 
                    if (j < 4) a[i+1][j+1] = 0;
                }
                if (j > 0) a[i][j-1] = 0; 
                if (j < 4) a[i][j+1] = 0; 
               
            }
            printf("%d ", a[i][j]);
        }
        printf("\n");
    }
    return 0;
}

输出

Random Matrix :
1 0 1 1 1 
1 0 0 1 1 
0 1 0 1 1 
0 0 0 0 0 
1 0 1 1 0 
---------
Filtered Matrix :
1 0 1 0 1 
0 0 0 0 0 
0 1 0 1 0 
0 0 0 0 0 
1 0 1 0 0 

【讨论】:

  • 在先前擦除的单元格上写入 1 不一定是问题,因为与擦除关联的先前写入的 1 本身会被擦除。因此,最终结果仍然满足练习的标准。做你描述的工作本身并没有错,但我觉得它甚至不如 OP 的原版那么干净,他们要求更干净的东西。
  • 当我测试它时,OP 代码产生了许多错误(检测到堆栈粉碎),所以实际上,我不会说它是“干净的”。此外,使用OP技术,处理后的矩阵中保持4'1',而使用两步技术,它仍然保持7,并且两种情况都满足要求。但我承认在矩阵中保持最大“1”不是 OP 的要求。无论如何感谢您的评论。
【解决方案2】:

除了越界访问数组,你的程序没问题。这是一种更通用的方法,适用于大于 1 个单元格的范围

#include <stdio.h>
#include <stdlib.h>

#define ROW 5
#define COL 5
#define RAN 1 // range

int main() {

    int a[ROW][COL];
    
    for (int i = 0; i < ROW; i++) {
    
        for (int j = 0; j < COL; j++) {
        
            if( (a[i][j] = rand() % 2) ) {
                
                for(int k = i-RAN; k <= i+RAN && k < ROW; k++) {
                    
                    for(int l = j-RAN; l <= j+RAN && l < COL; l++) {
                        
                        if( k >= 0 && l >= 0 && !(k == i && l == j)) {
                            
                            a[k][l] = 0;
                        }
                    }
                }
            }
        }
    }
    
    for (int i = 0; i < ROW; i++) {
    
        for (int j = 0; j < COL; j++) {
            
            printf("%d ", a[i][j]);
        }
        puts("");
    }
    
    return 0;
}

【讨论】:

    【解决方案3】:

    有一种更简单的方法可以做到这一点:您需要使用曼哈顿公式。所以,代码可以是:

    int distance = sqrt(pow((x1-x2),2) + pow((y1-y2),2))
    

    其中 x1, y1 是我的单元格的坐标,x2, y2 是包含 1 的其他单元格的坐标。如果距离

    【讨论】:

      【解决方案4】:

      我认为没有更简单或更清洁的方法来完成这项工作。您的代码很清晰,并且尽可能简短。还有一些替代品具有更好的属性,例如不将1s 的外观偏向边缘,尤其是矩阵的右下角,但这是一个不同的标准。

      正如我在 cmets 中所写,您确实需要避免超出数组的边界(这会使您的代码更加复杂),当然也没有必要将 0 添加到您的随机数中。

      您也许可以通过以其他方式对矩阵进行编码,例如在unsigned char 的数组中按位编码,从而更巧妙地做到这一点,但这不会更简单,也可能不会更简洁,或者。

      解决溢出问题的一种非常简洁的方法可能是将数组声明为每个维度中较大的两个元素,并对实际元素使用从一开始的索引。这将在真实数据的所有方面提供一个边距,这样您的所有写入都在实际数组的范围内,即使有些超出了有意义的数据。那就是:

      int a[7][7] = {0};  // a[1][1] ... a[5][5] will contain the real data
      
      for (int i = 1; i < 6; i++) {
          for (int j = 1; j < 6; j++) {
              a[i][j] = rand() % 2;
              if (a[i][j] == 1) {
                  a[i-1][j-1] = 0; 
                  // ...
              }
          }
      }
      

      您将生成的实际矩阵视为仅具有1 &lt;= i &amp;&amp; i &lt;= 51 &lt;= j &amp;&amp; j &lt;= 5 的元素。那么,使用i - 1j + 1 之类的索引并不重要,因为这些对真实数据的所有ij 都有效。

      【讨论】:

        【解决方案5】:

        您的代码有一个问题:您写入的矩阵单元格的坐标超出了 0..4 范围。

        这是修改后的版本:

        for (int i = 0; i < 5; i++) {
            for (int j = 0; j < 5; j++) {
                a[i][j] = 0;
                if (rand() % 2) {
                    for (int ii = i - 1; i <= i + 1; i++) {
                        if (ii >= 0 && ii < 5) {
                            for (jj = j - 1; j <= j + 1; j++) {
                                if (jj >= 0 && jj < 5)
                                    a[ii][jj] = 0;
                            }
                        }
                    }
                    a[i][j] = 1;
                }
            }
        }
        

        【讨论】:

          【解决方案6】:

          一些想法

          您的代码是循环中的循环。对于 2D 数组,您可以考虑在一个循环中完成所有操作。对于小型阵列,即:1-5 这真的没关系。对于较大的数组,如果您计算 i,j 作为数组的函数,您的算法将更快。 见:Map a 2D array onto a 1D array

          您还可以将变量命名为 'a' 'i',j 类似 row、col 或更有意义的名称,具体取决于代码的缩进用途。

          另一部分让我有点困惑。假设您的阵列是 5x5 并且还假设您的最终目标是确保每个“1”总是有 8 零的邻居,一旦第一个随机数生成产生“1”并强制 8 个邻居为零,则不再需要更新多达 4 个邻居。 (i,j+1)/(i+1,j)/(i+1,j+1)/(i-1,j)。正如@Weather Vane 所指出的,您正在覆盖您的工作,这可能是您获得“冗余”感觉的地方。

          #define MAX_ARRAY 5
          
          
          int in_bounds(int row,int col)
          {
          if (row >= MAX_ARRAY) return 0;
          if (col >= MAX_ARRAY) return 0;
          return 1;
          }
          
          void print_matrix (int matrix[MAX_ARRAY][MAX_ARRAY],int size)
          {
          
          for (int i=0;i<size;i++)
           {
           for (int j=0;j<size;j++)
            {
            fprintf(stdout,"%d",matrix[i][j]);
          //  fprintf(stdout,"%d,%d ",i,j);
            }
           fprintf(stdout,"\n");
          
           }
          }
          
          int main()
          {
          //for stack overflow: https://stackoverflow.com/questions/65398722/is-there-a-cleaner-way-to-write-this-c-code/65399364#65399364
             srand(time(0));
              int matrix[MAX_ARRAY][MAX_ARRAY];
               memset(matrix, -1, sizeof(int) * MAX_ARRAY * MAX_ARRAY);
            
              for (int counter=0;counter<MAX_ARRAY * MAX_ARRAY;counter++)
                {
                int col=counter / MAX_ARRAY;
                int row=counter % MAX_ARRAY;
          
                if (matrix[row][col] == -1)
                  {
                  matrix[row][col] = rand() %2;
                  if (matrix[row][col] == 1)
                   {
                      if (in_bounds(row,col+1)) matrix[row][col+1] = 0;
                      if (in_bounds(row+1,col)) matrix[row+1][col] = 0;
                      if (in_bounds(row+1,col+1)) matrix[row+1][col+1] = 0;
                      if (in_bounds(row-1,col)) matrix[row-1][col] = 0;
                      if (in_bounds(col,row-1)) matrix[col][row-1] = 0;
                      if (in_bounds(row-1,col-1)) matrix[row-1][col-1] = 0;
                      if (in_bounds(row-1,col+1)) matrix[row-1][col+1] = 0;
                      if (in_bounds(row+1,col-1)) matrix[row+1][col-1] = 0;
                  }
                 }
          
            }
          print_matrix(matrix,MAX_ARRAY);
          }    
          

          【讨论】:

            猜你喜欢
            • 2017-05-13
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-01-11
            • 2021-08-11
            • 2011-06-28
            • 1970-01-01
            • 2013-07-07
            相关资源
            最近更新 更多