在2D(10x10)int数组中更换重复元素的有效方法是什么?

时间:2014-03-21 00:58:08

标签: c arrays

我已经生成了一个10x10整数矩阵,通过二维数组,元素是随机生成的并且位于

1 <= z <= 5. 

我需要一种有效的方法,将长度为3或更大的任何行或列(非对角线)的所有相邻“重复”(重复元素)设置为整数六(6)。为了清楚起见,遵循粗暴方法的来源。

for(row=0;row<10;row++)
{
    for(col=0;col<10;col++)
    {
        board[row][col]=rand()%4+1; //filling matrix here
    }
}
print_board(board, row, col);

printf("Switch: ROW COLUMN\n ");
scanf("%hu %hu", &x1, &y1);
printf("With: ROW COLUMN\n");
scanf("%hu %hu", &x2, &y2);
swap(board, x1, y1,x2, y2);  //stdrd for loop no good b/c of
                             //below <-this->below    
if(board[0][0]==board[0][1] && board[0][1]==board[0][2] && board[0][2]==board[0][3])
{
    board[0][0]=6;
    board[0][1]=6;  
    board[0][2]=6;
    board[0][3]=6;   // brute force would require many more to complete 
}

我知道必须存在比列出所有排列更优雅的方法。如果您已经看到这个并回想起这项技术,我将非常感谢您的帮助。 C-Monster

3 个答案:

答案 0 :(得分:2)

我不确定是否有更优雅的方式来实现它,我正在提供我现在所做的。

  1. 如果你想获得[1,5],请使用rand()%5 + 1。
  2. 示例只显示1     方向,从左到右依次排列,需要考虑     如果需要,可以使用列和对角线,注意您可能需要一个状态数组     标记是否比较了元素。
  3. 一个优化,如果是     相邻元素不同,不需要比较后面     元素,从新的元素开始。例如,如果a[0][0]==a[0][1] && a[0][1] != a[0][2],则不需要比较[0] [1]和[0] [3-9],从比较a [0] [2]和[0]开始[3-] 9]。
  4. `

    int main()
    {
        int board[10][10];
        int row=0,col=0;
        srand((unsigned int)(time(NULL)));
        for (row=0;row<10;++row)
        {
            for(col=0;col<10;++col)
            {
                board[row][col] = rand()%5 + 1;
                printf("%d ", board[row][col]);
            }
            printf("\n");
        }
        int count = 1;
        int seek = 0;
        for(row=0;row<10;++row)
        {
            for(col=1;col<8;++col) //compare at least 3 elements
            {
                for(seek=col+1;seek<10;)
                {
                    if(board[row][col] == board[row][seek])
                    {
                        ++count;
                        ++seek;
                    }
                    else
                    {
                        col = seek-1;
                        break; //change the start element
                    }
                }
                if (count >= 3)
                {
                    //print the found location
                    //printf("%d  %d\n", row, seek-1);
                    int i;
                    for(i=seek-1;count>=1;--count)
                        board[row][i--] = 6;
                }
                count = 1;
            }
        }
        //print the result
        for (row=0;row<10;++row)
        {
            for(col=0;col<10;++col)
            {
                printf("%d ", board[row][col]);
            }
            printf("\n");
        }
        return 0;
    }
    

    `

答案 1 :(得分:1)

对于每一行,扫描列。读取一个元素,然后向前扫描列,直到到达最后一列,或者找到一个具有不同值的元素。如果跨度的长度大于或等于3,请返回并将所有元素设置为6.如果尚未到达最后一列,请从导致您停止的元素继续扫描。

答案 2 :(得分:1)

您的问题非常适合以SIMD方式进行,因为SIMD会并行比较连续数据的操作。这种方法的运行速度明显快于任何类型的普通C代码。 我假设您的board[][]int类型。有一个例子可以在我的MinGW上正常工作。您需要为SSE2内在函数添加标头intrin.hemmintrin.h。 您可以替换代码中的所有10来调整board的大小。

#include <emmintrin.h>

int main(){
    int board[10][10];
    int row, col;
    for(row=0;row<10;row++){
        for(col=0;col<10;col++){
            board[row][col]=rand()%2+1; //filling matrix here
            printf("%d ", board[row][col]);
        }
        printf("\n");
    }
    printf("\n");
    for(row=0;row<10;row++){
        col = 0;
        while(col <= 10 - 4){
            __m128i xmm0 = _mm_loadu_si128((__m128i*)&board[row][col]);
            __m128i xmm1 = _mm_set1_epi32(board[row][col]);
            __m128i xmm2;
            __m128i xmm6 = _mm_set1_epi32(6);
            __m128i xmmn = _mm_set1_epi32(-1);
            unsigned long c;
            int mask;

            xmm0 = _mm_xor_si128(_mm_cmpeq_epi32( xmm0, xmm1 ), xmmn);
            mask = _mm_movemask_epi8(xmm0);
            if (!mask){
                _mm_storeu_si128( (__m128i*)&board[row][col], xmm6 );
                col += 4;
                do{
                    if (col > 10 - 4) col = 10 - 4;
                    xmm0 = _mm_loadu_si128((__m128i*)&board[row][col]);
                    xmm2 = _mm_or_si128( _mm_cmpeq_epi8( xmm0, xmm1 ), _mm_cmpeq_epi8( xmm0, xmm6 ) );
                    xmm0 = _mm_xor_si128(xmm2, xmmn);
                    xmm0 = _mm_or_si128(_mm_slli_si128(xmm0, 4), xmm0);
                    xmm0 = _mm_or_si128(_mm_slli_si128(xmm0, 8), xmm0);
                    xmm2 = _mm_xor_si128(xmm0, xmmn);
                    _mm_maskmoveu_si128( _mm_set1_epi32(6), xmm2 , (char*)&board[row][col] );
                    mask = _mm_movemask_epi8(xmm0);
                    if (col == 10 - 4){
                        col++;
                        break;
                    }
                    c = __builtin_ctz(mask);/* In MSVC: _BitScanForward(mask, &c); */
                    c >>= 2;
                    col += c;
                }while(mask);
            }else{
                col += __builtin_ctz(mask) >> 2;
            }
        }
    }
    for(row=0;row<10;row++){
        for(col=0;col<10;col++){
            printf("%d ", board[row][col]);
        }
        printf("\n");
    }

    return 1;
}