【问题标题】:C language isMagicsquare function: What logic error is in my function code?C语言isMagicsquare函数:我的函数代码中有什么逻辑错误?
【发布时间】:2019-07-24 14:38:04
【问题描述】:

虽然我当前示例的输出是正确的,但我的代码似乎有一个逻辑错误,在其他情况下没有给出正确的输出。

我之前已经解决过这个问题:

“如果没有重复的数字,所有数字都被使用,你的最后一列总和是正确的,但你的倒数第二列总和不正确,你的代码会发生什么?”

非常感谢任何帮助。

我当前的代码:

/* Magic Square */
#include <stdio.h>

#define MAX_N 100
#define TRUE  1
#define FALSE 0

int isMagicSquare(int square[MAX_N][MAX_N], int n);

int main(void) {
    int square1[MAX_N][MAX_N] = {
            {4, 9, 2},
            {3, 5, 7},
            {8, 1, 6}};

    // should print TRUE
    int check1 = isMagicSquare(square1, 3);
    if (check1 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    int square2[MAX_N][MAX_N] = {
            {20,  6,  7, 17},
            { 9, 15, 14, 12},
            {13, 11, 10, 16},
            { 8, 18, 19, 5} };

            /*{ 1 , 2 , 3 , 4 , },
            { 5 , 6 , 7 , 8 , },
            { 9 , 10, 11, 12, },
            { 13, 14, 15, 16,} };*/

            /*{16, 2, 3, 13,}, 
            {5, 11, 10, 8 ,},
            {9,  7, 6, 12 ,},
            {4, 14, 15, 1, } };*/ 

    // should print FALSE
    int check2 = isMagicSquare(square2, 4);
    if (check2 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    int square3[MAX_N][MAX_N] = {
            {17, 24,  1, 15,  8},
            {23,  5,  7, 16, 14},
            { 4,  6, 13, 22, 20},
            {10, 12, 19,  3, 21}, 
            {11, 18, 25,  9,  2}};

    // should print FALSE
    int check3 = isMagicSquare(square3, 5);
    if (check3 == TRUE) {
        printf("TRUE\n");
    } else {
        printf("FALSE\n");
    }

    return 0;
}

int isMagicSquare(int square[MAX_N][MAX_N], int n) {
    int row, col;
    int drow, dcol;
    int sum, sum1, sum2, sum3;
    int boolean = 0;

    //For Diagonals
    sum = 0;
    for (row = 0; row < n; row++) {
        for (col = 0; col < n; col++) {
            if (row == col)
                sum += square[row][col];
        }
    }

    for (row = 0; row < n; row++) {
        sum3 = 0;
        for (col = 0; col < n; col++) {
            sum3 += square[n-row-1][col]; 
        }
        if (sum == sum3)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    //For Rows
    for (row = 0; row < n; row++) {
        sum1 = 0;
        for (col = 0; col < n; col++) {
            sum1 = sum1 + square[row][col];
        }
        if (sum == sum1)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    //For Columns
    for (row = 0; row < n; row++) {
        sum2 = 0;
        for (col = 0; col < n; col++) {
            sum2 = sum2 + square[col][row];
        }
        if (sum == sum2)
            boolean = 1;
        else {
            return FALSE;
        }
    }

    if (boolean == 1) {
        //Check if All Numbers is used

        for (row = 0; row < n; row++) {
            for (col = 0; col < n; col++) {
                if(square[row][col] > n*n || square[row][col] < 0) {
                    boolean = 0;
                    break;
                }
            }
        }

        //Check for Repeating Numbers
        for (row = 0; row < n; row++) {
            for(col = 0; col < n; col++) {

                for(drow = row + 1; drow < n; drow++){
                    for(dcol = col + 1; dcol < n; dcol++) {
                        if(square[row][col] == square[drow][dcol]) {
                            boolean = 0;
                            break;
                        }
                    }   
                }
            }
        }
        // if Statement End
    }
    else {
        boolean = 0;
    }

    if (boolean == 1)
        return TRUE;
    else
        return FALSE;
}

【问题讨论】:

  • ...它可以工作,但有一个错误?我们可能会以不同的方式使用这个词。您如何识别错误?
  • 您的对角线检查可能是错误的。它似乎在循环所有可能的对角线,而不仅仅是两个主对角线。您应该将打印代码添加到您的 isMagicSquare 函数中,以便识别它正在检查什么以及为什么会做出这样的决定。
  • //Check if All Numbers is used 代码效率极低O(n*n*n*n)MAX_N 100 的合理关注。另一种方法可以对值进行排序,然后检查 therm O(n* log n)
  • @Vinxent:您提交的内容可能与您在开发和调试代码时编写的内容不同。你可以考虑#define macro for debug printing in C,但这可能有点过头了。在调试时,添加打印语句。当您提交代码时,将其注释掉,或将其删除;他们已经达到了他们的目的。或者,如果您使用调试宏,请保留它们 - 只需禁用调试即可。
  • @Vinxent 时间(或空间)复杂度,又称大 O 表示法。

标签: c arrays function for-loop


【解决方案1】:

您可以使用更紧凑的方案来检查所有数字1 .. (n*n) 是否使用了没有重复的代码,例如:

int counts[n * n];  // Can't use an initializer with a VLA
memset(counts, '\0', sizeof(counts));

for (int i = 0; i < n; i++)
{
    for (int j = 0; j < n; j++)
    {
        if (square[i][j] <= 0 || square[i][j] > n * n)
            return FALSE;
        counts[square[i][j] - 1]++;  // Map 1..n*n to 0..n*n-1
        // if (++counts[square[i][j] - 1] > 1)
        //     return FALSE;
    }
}

for (int i = 0; i < n * n; i++)
{
    if (counts[i] != 1)
        return FALSE;
}

由于要检查 n*n 元素,因此此代码使用的空间和时间与幻方中的元素数量呈线性关系,该数量在最佳常数因子内。

【讨论】:

    【解决方案2】:

    似乎 sum3 var 在计算循环内重新初始化为 0,加上对角和相等性检查应该在循环外。

    我会这样修改它:

    //For Diagonals
    sum = 0;
    sum3 = 0;
    for (row = 0; row < n; row++) {
        sum  += square[row][row];
        sum3 += square[row][n - 1 - row];
    }
    if (sum == sum3)
        boolean = 1;
    else {
        return FALSE;
    }
    

    顺便说一句,我稍微简化了对角线计算,因为它是线性的,不需要 2 个嵌套循环。

    我在最终检查中发现了一些其他错误:

    -0 不应是有效值

    -return 而不是仅仅break(break只存在内循环,外循环继续)

    for (row = 0; row < n; row++) {
        for (col = 0; col < n; col++) {
            if(square[row][col] > n*n || square[row][col] <= 0) {
                return FALSE;
            }
        }
    }
    
    //Check for Repeating Numbers
    int storedNumbers[n * n];
    for (row = 0; row < n; row++) {
        for(col = 0; col < n; col++) {
            storedNumbers[row + n * col] = square[row][col];
        }
    }
    

    然后扫描 storedNumbers 是否有重复项。 Searching for duplicate values in an array

    干杯

    【讨论】:

    • 代码有效(对于其他情况)!所以对角线是问题所在。非常感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-05
    • 1970-01-01
    • 2019-01-16
    • 2012-01-03
    • 1970-01-01
    • 2021-05-06
    • 1970-01-01
    相关资源
    最近更新 更多