001: #include<stdio.h>
002: #include<stdlib.h>
003: #include<time.h>
004:
005: void mprint(int n, int m[n][n]);
006: int ncheck(int n, int m[n][n]);
007: int rowcheck(int r, int n, int m[n][n]);
008: int colcheck(int c, int n, int m[n][n]);
009: int diacheck(int d, int n, int m[n][n]);
010:
011: int main(int argc, char **argv){
012:
013: int flag_magica = 1; // uso questa variabile per tener traccia se la matrice e' o meno un quadrato magico valido
014:
015: // LETTURA MATRICE
016:
017: // per semplicita' passo nome file da riga di comando, comunque non specificato nel testo
018: FILE *fp = fopen(argv[1], "r");
019: if(!fp)
020: {
021: perror("");
022: exit(EXIT_FAILURE);
023: }
024: int n;
025: fscanf(fp, "%d", &n);
026:
027: // se alloco nella main() posso permettermi di usare VLA
028: int m[n][n];
029: for(int r=0; r<n; r++)
030: for(int c=0; c<n; c++)
031: fscanf(fp, "%d", &m[r][c]);
032: //mprint(n, m);
033: //printf("\n");
034:
035: printf("%s: ", argv[1]);
036:
037: // VERIFICA MAGICA
038:
039: // verifico contenga tutti valori tra 1 e n*n
040: flag_magica = ncheck(n, m);
041:
042:
043:
044: // uso somma prima riga come valore "campione"
045: int tot = rowcheck(0, n, m);
046: int tmp;
047:
048: // verifica righe
049: for(int r = 1; r < n && flag_magica; ++r)
050: if(tot != (tmp = rowcheck(r, n, m)))
051: {
052: printf("riga %d diversa da riga 0 (%d != %d)\n", r, tmp, tot);
053: flag_magica = 0;
054: }
055:
056: // verifica colonne
057: for(int c = 0; c < n && flag_magica; ++c)
058: if(tot != (tmp = colcheck(c, n, m)))
059: {
060: printf("colonna %d diversa da riga 0 (%d != %d)\n", c, tmp, tot);
061: flag_magica = 0;
062: }
063:
064: // verifica diagonali
065: if(flag_magica)
066: {
067: if(tot != (tmp = diacheck(0, n, m)))
068: {
069: printf("diagonale principale ha somma diversa da quella di riga 0 (%d != %d)\n", tmp, tot);
070: flag_magica = 0;
071: }
072:
073: if(tot != (tmp = diacheck(1, n, m)))
074: {
075: printf("diagonale secondaria ha somma diversa da quella di riga 0 (%d != %d)\n", tmp, tot);
076: flag_magica = 0;
077: }
078: }
079:
080: if(flag_magica)
081: printf("VALIDA\n");
082:
083: return 0;
084: }
085:
086: void mprint(int n, int m[n][n])
087: {
088: for(int r=0; r<n; r++)
089: {
090: for(int c=0; c<n; c++)
091: printf("%2d ", m[r][c]);
092: printf("\n");
093: }
094: }
095:
096: int rowcheck(int r, int n, int m[n][n])
097: {
098: if(r >= n)
099: {
100: printf("Errore in rowcheck(), indice colonna richiesto (%d) >= dimensione matrice (%d)\n", r, n);
101: exit(EXIT_FAILURE);
102: }
103:
104: int sum = 0;
105:
106: for(int c=0; c<n; c++)
107: sum += m[r][c];
108:
109: // DEBUG printf("Riga #%d ha somma %d\n", r, sum);
110: return sum;
111: }
112:
113:
114: int colcheck(int c, int n, int m[n][n])
115: {
116: if(c >= n)
117: {
118: printf("Errore in rowcheck(), indice riga richiesto (%d) >= dimensione matrice (%d)\n", c, n);
119: exit(EXIT_FAILURE);
120: }
121:
122: int sum = 0;
123:
124: for(int r=0; r<n; r++)
125: sum += m[r][c];
126:
127: // DEBUG printf("Colonna #%d ha somma %d\n", c, sum);
128: return sum;
129: }
130:
131:
132: // d=0 -> diagonale principale, d=1 -> diagonale secondaria
133: int diacheck(int d, int n, int m[n][n])
134: {
135: if(d >= 2)
136: {
137: printf("Errore in diacheck(), indice colonna puo' essere solo 0 o 1\n");
138: exit(EXIT_FAILURE);
139: }
140:
141: int sum = 0;
142:
143: if(!d)
144: for(int r=0, c=0; r<n; r++, c++)
145: sum += m[r][c];
146: else
147: for(int r=0, c=n-1; r<n; r++, c--)
148: sum += m[r][c];
149:
150: // DEBUG printf("Diagonale #%d ha somma %d\n", d, sum);
151: return sum;
152: }
153:
154: int ncheck(int n, int m[n][n])
155: {
156: int *flag = calloc(n*n, sizeof(int)); // array che ha come indici i valori da 0 fino a n*n-1 e inizializzato a tutti 0
157:
158: for(int r=0; r<n; r++)
159: for(int c=0; c<n; c++)
160: if(m[r][c] < 0 || m[r][c] > n*n) // verifico che la matrice contenga numeri nell'intervallo corretto
161: {
162: printf("Valore della matrice fuori intervallo (%d)\n", m[r][c]);
163: return 0;
164: }
165: else
166: flag[ m[r][c] - 1] = 1; // metto a 1 l'elemento dell'array che ha come indice il valore della matrice - 1
167:
168: // se la matrice ha tutti i valori da 1 a n*n, il precedente ciclo mette a 1 TUTTI gli elementi dell'array
169: // verifichiamo sia successo cosi'
170: for(int i = 0; i < n*n; ++i)
171: if(! flag[i] )
172: {
173: printf("la matrice non contiene il valore %d\n", i+1);
174: return 0;
175: }
176:
177: // se arrivo qui, era tutto a 1
178: return 1;
179:
180: }
181:
182: