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: