#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>

int takeInput(unsigned int* matrixSize, int*** matrix);
void checkArray(unsigned int matrixSize, int** matrix);

/**************************************************
 *
 * @brief - Entry point of the program.
 *
 **************************************************/

int main()
{
    unsigned int matrixSize = 0;
    int** matrix = NULL;

    if (takeInput(&matrixSize, &matrix) == 0)
    {
        checkArray(matrixSize, matrix);
    }

    for (unsigned int i = 0; i < matrixSize; i++)
    {
        free(matrix[i]);
    }
    free(matrix);

    return 0;
}

/**************************************************
 *
 * @brief - Takes input for the size and elements 
 * of a square matrix.
 * 
 * @param matrixSize - Pointer to store the size of 
 * the matrix.
 * 
 * @param matrix - Pointer to store the address of 
 * the matrix.
 *
 **************************************************/

int takeInput(unsigned int* matrixSize, int*** matrix)
{
	printf("Enter the size of the square matrix: ");
	scanf_s("%u", matrixSize);

	if (*matrixSize < 2 || *matrixSize > 10)
	{
		printf("Invalid matrix size!\n");
		return -1;
	}

	*matrix = (int**)malloc(*matrixSize * sizeof(int*));

	for (unsigned int i = 0; i < *matrixSize; i++)
	{
		(*matrix)[i] = (int*)malloc(*matrixSize * sizeof(int));
	}

	printf("Enter the elements of the square matrix:\n");

	for (unsigned int i = 0; i < *matrixSize; i++)
	{
		for (unsigned int j = 0; j < *matrixSize; j++)
		{
			printf("[%u][%u]: ", i, j);
			scanf_s("%d", &(*matrix)[i][j]);
		}
	}

	return 0;
}

/**************************************************
 *
 * @brief - Checks the symmetry of the matrix along 
 * the main diagonal, secondary diagonal, middle 
 * row, and middle column.
 * 
 * @param matrixSize - Size of the matrix.
 * 
 * @param matrix - The square matrix to be checked.
 *
 **************************************************/

void checkArray(unsigned int matrixSize, int** matrix)
{
    bool mainDiagSym = true;
    bool secDiagSym = true;
    bool midRowSym = true;
    bool midColSym = true;

    unsigned int mid = matrixSize / 2;

	// Main diagonal
    for (unsigned int i = 1; i < matrixSize; i++) {
        if (matrix[i][i] != matrix[0][0]) {
            mainDiagSym = false;
            break;
        }
    }

	// Secondary diagonal
    for (unsigned int i = 1; i < matrixSize; i++) {
        if (matrix[i][matrixSize - 1 - i] != matrix[0][matrixSize - 1]) {
            secDiagSym = false;
            break;
        }
    }

    // Middle row
    for (unsigned int j = 1; j < matrixSize; j++) {
        if (matrix[mid][j] != matrix[mid][0]) {
            midRowSym = false;
            break;
        }
    }

	// Middle column
    for (unsigned int i = 1; i < matrixSize; i++) {
        if (matrix[i][mid] != matrix[0][mid]) {
            midColSym = false;
            break;
        }
    }

    printf("Symmetric by main diagonal: %s\n", mainDiagSym ? "Yes" : "No");
    printf("Symmetric by secondary diagonal: %s\n", secDiagSym ? "Yes" : "No");
    printf("Symmetric by middle row: %s\n", midRowSym ? "Yes" : "No");
    printf("Symmetric by middle column: %s\n\n", midColSym ? "Yes" : "No");

    for (unsigned int i = 0; i < matrixSize; i++)
    {
        for (unsigned int j = 0; j < matrixSize; j++)
        {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
}