arrayscalgorithmmatrixmagic-square

Why the result changes after i change the size of array?


I ve done a program that take an number n as input and then return a square matrix n*n with the property that all row, columns, and diagonals have the same sum.

The project works without problem, and I tried to optimize it as much as i can, from the algorithm to uses the specific data type for this(in my case unsigned short, cause i didn t need a bigger storage).

After all i tried to see the performance and i wanted to try it with a bigger number like 100,200, so on; But when i tried to change the storage of matrix the program didn t work properly and returned a matrix with 0 and the sum was strange.

I don t understand from where is this bug.

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

unsigned short a[100][100], i = 0, j = 0, n, suma[100];

void next_b(unsigned short *i, unsigned short *j);   // find the properly i and j
void completare(unsigned short i, unsigned short j); // completes the matrix after i find the i and j
void tipar();                                        // print the matrix

int suma_linie(unsigned short x);   //sum of a row
int suma_coloana(unsigned short y); //sum of a column
int suma_diagonala_principala();    //first diagonal
int suma_diagonala_secundara();     //second one

int main()
{

    scanf("%hu", &n);
    system("cls");
    j = n / 2 - 1;
    a[0][j] = 4;
    a[0][j + 1] = 1;
    a[1][j] = 2;
    a[1][j + 1] = 3;

    suma[0] = 5;
    suma[1] = 5;
    suma[n + j] = 6;
    suma[n + j + 1] = 4;

    for (int x = 2; x <= (n / 2) * (n / 2); x++)
    {
        next_b(&i, &j);
        a[i][j] = x;
        completare(i, j);
    }
    tipar();
    //for(int x=0;x<n;x++){
    //
    //    printf("suma de pe linia %d este: %d\n",x,suma_linie(x));
    //    printf("suma de pe coloana %d este: %d\n\n",x,suma_coloana(x));
    //}
    //printf("suma de pe daig principala  este: %d\n\n",suma_diagonala_principala());
    //  printf("suma de pe daig secundara este: %d\n\n",suma_diagonala_secundara());

    for (int x = 0; x < 2 * n + 2; x++)
    {
        if (x < n)
        {
            printf("suma de pe linia %d este %hu\n", x, suma[x]);
        }
        else if (x < 2 * n)
        {
            printf("suma de pe coloana %d este %hu\n", x % n, suma[x]);
        }
        else if (x == 2 * n)
        {
            printf("suma de pe diag principala este %hu\n", suma[x]);
        }
        else
        {
            printf("suma de pe diag secundara este %hu\n", suma[x]);
        }
    }
    return 0;
}

void tipar()
{

    for (int k = 0; k < n; k++)
    {
        for (int l = 0; l < n; l++)
        {

            if (a[k][l] < 10)
            {
                printf("   %d |", a[k][l]);
            }
            else if (a[k][l] <= 99)
            {
                printf("  %d |", a[k][l]);
            }
            else if (a[k][l] < 1000)
            {
                printf(" %d |", a[k][l]);
            }
            else if (a[k][l] < 10000)
            {
                printf("%d ", a[k][l]);
            }
        }
        printf("\n");
        for (int z = 0; z <= 6 * n - 1; z++)
        {
            printf("-");
        }
        printf("\n");
    }
    printf("\n");
}

void next_b(unsigned short *i, unsigned short *j)
{
    if (*i - 2 < 0)
    {

        if (a[n - 2][*j + 2] == 0 && *j + 2 <= n - 2)
        {
            // printf("cazul 2\n");
            *i = n - 2;
            *j += 2;
            return;
        }
        else if (a[*i - 2][*j] == 0)
        {
            // printf("cazul 7\n");
            *i += 2;
            return;
        }
    }

    else
    {
        if (*j == n - 2)
        { //printf("cazul 3\n");
            *i -= 2;
            *j = 0;
            return;
        }
        else if (a[*i - 2][*j + 2] != 0)
        {
            //printf("cazul 4\n");
            *i += 2;
        }
        else if (a[*i - 2][*j + 2] == 0)
        {
            //         printf("cazul 5\n");
            *i -= 2;
            *j += 2;
        }
    }
}

void completare(unsigned short i, unsigned short j)
{

    if (i <= n / 2)
    { //////////// l

        if (i == n / 2 - 1 && j == n / 2 - 1)
        {

            a[i][j + 1] = 4 * a[i][j];
            a[i + 1][j] = 4 * a[i][j] - 2;
            a[i + 1][j + 1] = 4 * a[i][j] - 1;
            a[i][j] = 4 * a[i][j] - 3;
        }
        else
        {
            a[i][j] = 4 * a[i][j];
            a[i][j + 1] = a[i][j] - 3;
            a[i + 1][j] = a[i][j] - 2;
            a[i + 1][j + 1] = a[i][j] - 1;
        }
    }
    else if (i == n / 2 + 1)
    { ///////////// u

        if (j == n / 2 - 1)
        {

            a[i][j] = 4 * a[i][j];
            a[i][j + 1] = a[i][j] - 3;
            a[i + 1][j] = a[i][j] - 2;
            a[i + 1][j + 1] = a[i][j] - 1;
        }
        else
        {

            a[i][j + 1] = 4 * a[i][j];
            a[i + 1][j] = 4 * a[i][j] - 2;
            a[i + 1][j + 1] = 4 * a[i][j] - 1;
            a[i][j] = 4 * a[i][j] - 3;
        }
    }
    else
    { ///////x

        a[i][j + 1] = 4 * a[i][j];
        a[i + 1][j + 1] = 4 * a[i][j] - 2;
        a[i + 1][j] = 4 * a[i][j] - 1;
        a[i][j] = 4 * a[i][j] - 3;
    }

    suma[i] += a[i][j] + a[i][j + 1];
    suma[i + 1] += a[i + 1][j] + a[i + 1][j + 1];
    suma[n + j] += a[i][j] + a[i + 1][j];
    suma[n + j + 1] += a[i][j + 1] + a[i + 1][j + 1];

    if (i == j)
    {
        suma[2 * n] += a[i][j] + a[i + 1][j + 1];
    }
    if (i + j + 1 == n - 1)
    {
        suma[2 * n + 1] += a[i + 1][j] + a[i][j + 1];
    }
}

int suma_linie(unsigned short x)
{
    int s = 0;
    for (int y = 0; y < n; y++)
    {
        s += a[x][y];
    }
    return s;
}
int suma_coloana(unsigned short y)
{
    int s = 0;
    for (int x = 0; x < n; x++)
    {
        s += a[x][y];
    }
    return s;
}
int suma_diagonala_principala()
{
    int s = 0;

    for (int x = 0; x < n; x++)
    {

        s += a[x][x];
    }
    return s;
}
int suma_diagonala_secundara()
{
    int s = 0;

    for (int x = 0; x < n; x++)
    {

        s += a[x][n - x - 1];
    }
    return s;
}

The code is solve with an algorithm that i found on Wikipedia-Magic Square.

In the above cod if i try to change suma size to 200 for example or any other value, the program works strange and returns stupid things. It s valid even i set a size higher.

I used two ways to see the sum, one with a predefined functions and the other adding the matrix element to suma, the functions used int and the other method utilize unsigned short if its matters.


Solution

  • I checked your code and found some problems. I tried with n = 90.

    for(int x=2; x<=(n/2)*(n/2); x++)
    {
       next_b(&i,&j);
       a[i][j]=x;
       completare(i,j);
    
    }
    

    If you check this code then you can see when the value of i, j become 0, 2 accordingly then it goes to next_b(i, j) method. And there are some lines which are trying to access negative indexes. So it throws exception. Like -

    else if(a[*i-2][*j]==0)  // here
    {
        // printf("cazul 7\n");
        *i+=2;
        return;
    
    }
    

    .............................................

    if(*j==n-2)
    {
        //printf("cazul 3\n");
        *i-=2;
        *j=0;
        return;
    }
    else if (a[*i-2][*j+2]!=0) // here
    {
        //printf("cazul 4\n");
        *i+=2;
    
    }
    else if(a[*i-2][*j+2]==0)  // here
    {
        //printf("cazul 5\n");
        *i-=2;
        *j+=2;
    }
    

    Try to fix these negative indexing and then it should work (Assuming your approach is correct).