1 /*
2 * judge.c
3 *
4 * Created on: 2017年5月24日
5 * Author: ygh
6 * Algorithms thoughts:
7 * Using bucket sort latest significant Digit
8 * 1.sort id
9 * 2.sort perfect solution
10 * 3.sort total scores
11 */
12 #include <stdio.h>
13 #include <stdlib.h>
14 #define MAX_QUESTION 5
15 #define MAX_USER_DIGIT 5
16 #define MAX_USER 100000
17
18 /*
19 * The radix of the perfect times,it from 0 to MAX_QUESTION
20 */
21 #define BUCKET_RADIX_PERFECT 6
22
23 /*
24 * The radix of total score,the value if from 0 to 9
25 */
26 #define BUCKET_RADIX_TOTALSCORE 10
27 /*
28 * The score max digit
29 */
30 #define MAX_DIGIT 6
31
32 typedef struct node {
33 /*
34 * The id of the user
35 */
36 int id;
37 /*
38 * A integer array to record the score of
39 * each question
40 */
41 int solution[MAX_QUESTION];
42
43 /*
44 * The times about the prefer solution times
45 */
46 int perfectCouner;
47
48 /*
49 * The total score
50 */
51 int totalScore;
52
53 /*
54 * The rank of the user
55 */
56 int rank;
57
58 int showFlag;
59
60 } userArr[MAX_USER];
61
62 typedef struct node1 *ptrToSet;
63 typedef struct node1 {
64 /*
65 * A array of node to store the user's datas
66 */
67 userArr arr;
68 /*
69 * A integer to implement table sort
70 */
71 int table[MAX_USER];
72 /*
73 * A integer array record the whole scores of the questions
74 */
75 int question[MAX_QUESTION];
76 };
77
78 /*
79 *Create empty set of users and initialize the
80 *solution all to -2 standing for question no submit
81 *@param n The quantity of the users
82 *@param m The quantity of the question
83 */
84 ptrToSet createEmptySet(int n, int k) {
85 ptrToSet set = (ptrToSet) malloc(sizeof(struct node1));
86 int i, j;
87 for (i = 0; i < n; i++) {
88 set->table[i] = i;
89 for (j = 0; j < k; j++) {
90 set->arr[i].solution[j] = -2;
91 set->arr[i].perfectCouner = 0;
92 set->arr[i].id = i;
93 set->arr[i].showFlag = 0;
94 }
95 }
96 return set;
97 }
98
99 /*
100 * Insert question total scores into set
101 * @param set A point to point the set of users
102 * @param m The quantity of the question
103 *
104 */
105 void insertQuestionScore(ptrToSet set, int k) {
106 int score, i;
107 for (i = 0; i < k; i++) {
108 scanf("%d", &score);
109 set->question[i] = score;
110 }
111 }
112
113 /*
114 * Insert user's submit to set
115 * If the score is not than before,don't update,otherwise update it
116 * If the score is -1,update it into 0.
117 * If current score is equal question whole score,<code>perfectCounter</code>
118 * increase
119 * @param set A point to point the set
120 * @param m The quantity of the submit
121
122 */
123 void insertUser(ptrToSet set, int m) {
124 /*
125 * @param The id of user,it is a positive integer number
126 * @param The id of question,it is a positive integer number
127 * @param score The score this submit geting
128 */
129 int id, qId, score, i;
130 for (i = 0; i < m; i++) {
131 scanf("%d %d %d", &id, &qId, &score);
132 /*
133 * Because the index in array begin from zreo
134 * In order to be compatible
135 */
136 id--;
137 qId--;
138 if (set->arr[id].solution[qId] < score) {
139 set->arr[id].solution[qId] = score;
140 if (score == set->question[qId]) {
141 set->arr[id].perfectCouner++;
142 }
143 }
144 }
145
146 }
147
148 /*
149 * Calculate the total score
150 * We don't decrease scores,if the score is negative number
151 * we let it to zero and add it.But we need the negative number as
152 * a flag when we print the submit result:
153 * 1.The use never submitted,print '-'
154 * 2.The user submit but don't pass compiler get zeor,but we need
155 * print zero to console
156 * 3.If the total score is zero,we don't show them
157 */
158 void calculateTotalSource(ptrToSet set, int n, int k) {
159 int i, j;
160 int totalScore;
161 int scorce;
162 for (i = 0; i < n; i++) {
163 totalScore = -1;
164 for (j = 0; j < k; j++) {
165 scorce = set->arr[i].solution[j];
166 if (scorce < 0 && totalScore == -1) {
167 totalScore = -1;
168 } else if (scorce == 0 && totalScore == -1) {
169 totalScore = 0;
170 } else if (scorce > 0 && totalScore == -1) {
171 totalScore = scorce;
172 } else if(scorce > 0) {
173 totalScore += scorce;
174 }
175 }
176 set->arr[i].totalScore = totalScore;
177 }
178 }
179
180 void calculateShowFlag(ptrToSet set, int n) {
181 int i;
182 for (i = 0; i < n; i++) {
183 if (set->arr[i].totalScore > -1) {
184 set->arr[i].showFlag = 1;
185 } else {
186 set->arr[i].showFlag = 0;
187 set->arr[i].totalScore = 0;
188 }
189 }
190 }
191
192 typedef struct node2 *ptrToNode;
193 typedef struct node2 {
194 /*
195 * Store the id of the user
196 */
197 int key;
198
199 /*
200 * A point to point next node
201 */
202 ptrToNode next;
203
204 };
205
206 /*
207 * Define a data structure for bucket head that
208 * store the head point and rear point for the elements
209 */
210 typedef struct headNode {
211 ptrToNode head, rear;
212 };
213
214 /*
215 * Define a array of headNode to store the all buckets
216 */
217 typedef struct headNode bucket[BUCKET_RADIX_TOTALSCORE];
218
219 /*
220 * radix sort by perfect times in set.The perfect
221 * buckets is from 0 to <code>MAX_QUESTION</code>
222 * We sort uses according to perfect times DESC
223 * @param set A point to point the set
224 * @param n The quantity of users
225 */
226 void radixSortByPerfectTimes(ptrToSet set, int n) {
227 int di, i;
228 ptrToNode temp, list;
229 bucket b;
230 /*
231 * Initialize each bucket head and rear into NULL
232 */
233 for (i = 0; i < BUCKET_RADIX_PERFECT; i++) {
234 b[i].rear = b[i].head = NULL;
235 }
236 for (i = 0; i < n; i++) {
237 di = set->arr[i].perfectCouner;
238 temp = (ptrToNode) malloc(sizeof(struct node2));
239 temp->key = set->arr[i].id;
240 temp->next = NULL;
241 if (b[di].head == NULL) {
242 b[di].head = b[di].rear = temp;
243 } else {
244 b[di].rear->next = temp;
245 b[di].rear = temp;
246 }
247 }
248
249 /*
250 * Recover the elements has been deal with,using
251 * the list to point the head
252 */
253 list = NULL;
254 for (i = 0; i < BUCKET_RADIX_PERFECT; i++) {
255 if (b[i].head) {
256 b[i].rear->next = list;
257 list = b[i].head;
258 }
259 b[i].head = b[i].rear = NULL;
260 }
261
262 /*
263 * Set sorted sequence to table
264 */
265 for (i = 0; i < n; i++) {
266 temp = list;
267 list = list->next;
268 set->table[i] = temp->key;
269 free(temp);
270 }
271 }
272
273 /*
274 * Get the digit by the current number and current needed digit
275 * @param x The current number
276 * @param d The current digit
277 * @return The digit needed
278 */
279 int getDigit(int x, int d) {
280 int i;
281 int di;
282 for (i = 0; i < d; i++) {
283 di = x % BUCKET_RADIX_TOTALSCORE;
284 x = x / BUCKET_RADIX_TOTALSCORE;
285 }
286 return di;
287 }
288
289 /*
290 * Radix sort by total score
291 * @param set A point to point the set
292 * @param n The quantity of users
293 */
294 void radixSortByTotalScore(ptrToSet set, int n) {
295 int di, d, i, j;
296 ptrToNode temp, list;
297 bucket b;
298 /*
299 * Initialize each bucket head and rear into NULL
300 */
301 for (i = 0; i < BUCKET_RADIX_TOTALSCORE; i++) {
302 b[i].rear = b[i].head = NULL;
303 }
304 for (d = 1; d <= MAX_DIGIT; d++) {
305 for (j = 0; j < n; j++) {
306 di = getDigit(set->arr[set->table[j]].totalScore, d);
307 temp = (ptrToNode) malloc(sizeof(struct node2));
308 temp->key = set->table[j];
309 temp->next = NULL;
310 if (b[di].head == NULL) {
311 b[di].head = b[di].rear = temp;
312 } else {
313 b[di].rear->next = temp;
314 b[di].rear = temp;
315 }
316 }
317
318 /*
319 * Recover the elements has been deal with,using
320 * the list to point the head
321 */
322 list = NULL;
323 for (i = 0; i < BUCKET_RADIX_TOTALSCORE; i++) {
324 if (b[i].head) {
325 b[i].rear->next = list;
326 list = b[i].head;
327 }
328 b[i].head = b[i].rear = NULL;
329 }
330
331 /*
332 * Set sorted sequence to table
333 */
334 for (i = 0; i < n; i++) {
335 temp = list;
336 list = list->next;
337 set->table[i] = temp->key;
338 free(temp);
339 }
340
341 }
342 }
343
344 /*
345 * Calculate the rank
346 */
347 void calculateRank(ptrToSet set, int n) {
348 int rank = 1;
349 int totalScore = set->arr[set->table[0]].totalScore;
350 int i;
351 set->arr[set->table[0]].rank = rank;
352 for (i = 1; i < n; i++) {
353 if (set->arr[set->table[i]].totalScore == totalScore) {
354 set->arr[set->table[i]].rank = rank;
355 } else {
356 rank = i + 1;
357 totalScore = set->arr[set->table[i]].totalScore;
358 set->arr[set->table[i]].rank = rank;
359 }
360 }
361 }
362
363 /*
364 * Print the content of the set->table[i]
365 */
366 void toStingTable(ptrToSet set, int n) {
367 int i;
368 printf("table:");
369 for (i = 0; i < n; i++) {
370 printf("%d ", set->table[i]);
371 }
372 }
373
374 /*
375 * Get the digit of a number to print format
376 */
377 int getDiditumber(int num) {
378 int counter = 0;
379 while (num != 0) {
380 num = num / 10;
381 counter++;
382 }
383 return counter;
384 }
385
386 /*
387 * Print data to console
388 */
389 void toString(ptrToSet set, int n, int k) {
390 int i, j;
391 int digit;
392 for (i = 0; i < n; i++) {
393 if (set->arr[set->table[i]].showFlag == 0) {
394 continue;
395 }
396 printf("%d ", set->arr[set->table[i]].rank);
397 digit = getDiditumber(set->arr[set->table[i]].id + 1);
398 for (j = 0; j < (MAX_USER_DIGIT - digit); j++) {
399 printf("0");
400 }
401 printf("%d ", set->arr[set->table[i]].id + 1);
402 printf("%d ", set->arr[set->table[i]].totalScore);
403 for (j = 0; j < k; j++) {
404 if (set->arr[set->table[i]].solution[j] ==-2) {
405 printf("-");
406 } else if(set->arr[set->table[i]].solution[j] ==-1){
407 printf("0");
408 }else{
409 printf("%d",set->arr[set->table[i]].solution[j]);
410 }
411 if (j == k - 1) {
412
413 } else {
414
415 printf(" ");
416 }
417 }
418 printf("\n");
419 }
420 }
421
422 int main() {
423 int n, k, m;
424 scanf("%d %d %d", &n, &k, &m);
425 ptrToSet set = createEmptySet(MAX_USER, k);
426 insertQuestionScore(set, k);
427 insertUser(set, m);
428 n = MAX_USER;
429 // toString(set, n, k);
430 calculateTotalSource(set, n, k);
431 calculateShowFlag(set, n);
432 radixSortByPerfectTimes(set, n);
433 radixSortByTotalScore(set, n);
434 calculateRank(set, n);
435 toString(set, n, k);
436 return 0;
437 }