# FINAL 評分標準 ## 1. Fraction Arithmetic 正解及測試資料檔案: https://drive.google.com/file/d/1GslLrVxKkt4KUWCsx6fP15JVgGoCNLgj/view?usp=sharing 總共有 20 個測試資料,加減乘除照順序測試,每個函式各有 5 個。 若在執行該測試時遇到 error,則不會繼續進行測試,也不會得到後續的分數。 :::spoiler fin01.c ```c= #include <stdio.h> #include "frac.h" #define NUM_TESTS 20 void print_score(int32_t score, int failed_tests[]){ printf("%d, WA: ", score); for (int i = 0; i < NUM_TESTS; i++) { if (failed_tests[i] != 0) { printf("%d ", i + 1); } } printf("\n"); fflush(stdout); } int main() { int32_t score = 0; int32_t x, y; int failed_tests[NUM_TESTS] = {}; // Array to track failed tests for(int i = 0; i < NUM_TESTS; i++){ failed_tests[i] = -1; } int add_testx1[5] = {1, 0, 3, 87, 2147483647-87}; int add_testy1[5] = {2, 1, 4, 1073741819, 100}; int add_testx2[5] = {1, 1, -5, 2147482164, -100}; int add_testy2[5] = {3, 3, 6, 2147483638, 2147483647-56}; int add_ansx[5] = {5, 1, -1, 1073741169, 0}; int add_ansy[5] = {6, 3, 12, 1073741819, 0}; int add_ansisvalid[5] = {0, 0, 0, 0, -1}; for(int i = 0; i < 5; i++){ int isvalid = frac_add(&x, &y, add_testx1[i], add_testy1[i], add_testx2[i], add_testy2[i]); if(isvalid != add_ansisvalid[i]){ failed_tests[i] = 1; continue; } if(isvalid == -1 || (x == add_ansx[i] && y == add_ansy[i])){ score++; failed_tests[i] = 0; } else{ failed_tests[i] = 1; } } int del_testx1[5] = {3, 0, -1, 321, 1}; int del_testy1[5] = {4, 1, 2, 73, 0}; int del_testx2[5] = {1, 1, -1, 36482, 1}; int del_testy2[5] = {2, 3, 4, 675835, 2}; int del_ansx[5] = {1, -1, -1, 12604697, 0}; int del_ansy[5] = {4, 3, 4, 2902115, 0}; int del_ansisvalid[5] = {0, 0, 0, 0, -1}; for(int i = 0; i < 5; i++){ int isvalid = frac_del(&x, &y, del_testx1[i], del_testy1[i], del_testx2[i], del_testy2[i]); if(isvalid != del_ansisvalid[i]){ failed_tests[i+5] = 1; continue; } if(isvalid == -1 || (x == del_ansx[i] && y == del_ansy[i])){ score++; failed_tests[i+5] = 0; } else{ failed_tests[i+5] = 1; } } int mul_testx1[5] = {1, 0, 2147483647-1483, 1073741824, 1}; int mul_testy1[5] = {2, 1, (2147483647-9)/2, 1, 0}; int mul_testx2[5] = {2, 1, 2147483647-9, 4, 1}; int mul_testy2[5] = {3, 3, 2147483647-1483, 1, 2}; int mul_ansx[5] = {1, 0, 2, -1, -1}; int mul_ansy[5] = {3, 1, 1, 0, -1}; int mul_ansisvalid[5] = {0, 0, 0, -1, -1}; for(int i = 0; i < 5; i++){ int isvalid = frac_mul(&x, &y, mul_testx1[i], mul_testy1[i], mul_testx2[i], mul_testy2[i]); if(isvalid != mul_ansisvalid[i]){ failed_tests[i+10] = 1; continue; } if(isvalid == -1 || (x == mul_ansx[i] && y == mul_ansy[i])){ score++; failed_tests[i+10] = 0; } else{ failed_tests[i+10] = 1; } } int div_testx1[5] = {1, 0, -1, 1, 2147483647}; int div_testy1[5] = {2, 1, 2, 2, 1}; int div_testx2[5] = {1, 1, 1, 0, 1}; int div_testy2[5] = {3, 3, 4, 1, 2147483647}; int div_ansx[5] = {3, 0, -2, 0, 0}; int div_ansy[5] = {2, 1, 1, 0, 0}; int div_ansisvalid[5] = {0, 0, 0, -1, -1}; for(int i = 0; i < 5; i++){ int isvalid = frac_div(&x, &y, div_testx1[i], div_testy1[i], div_testx2[i], div_testy2[i]); if(isvalid != div_ansisvalid[i]){ failed_tests[i+15] = 1; continue; } if(isvalid == -1 || (x == div_ansx[i] && y == div_ansy[i])){ score++; failed_tests[i+15] = 0; } else{ failed_tests[i+15] = 1; } } print_score(score, failed_tests); return 0; } ``` ::: ## 2. Minesweeper Case1~Case6 1 分 Case7~Case8 3 分 Case9~Case11 1 分 ::: spoiler fin02.c ``` c #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include "mine.h" int main() { int32_t board[16][30] = {0}; for (int i = 0; i < 16; i++) { for (int j = 0; j < 30; j++) { scanf("%d", &board[i][j]); } } int row, col; while(scanf("%d %d", &row, &col) != EOF) { int state = hit(board, row, col); printf("%d\n", state); for (int i = 0; i < 16; i++) { for (int j = 0; j < 30; j++) { printf("%d ", board[i][j]); } printf("\n"); } } return 0; } ``` ::: [testcase](https://drive.google.com/drive/folders/1SILTJ-W_EYYp4uMjCIfEAonK5orxFeD7?usp=sharing) ## 3. Firewall - Case 1 (5pt) - 可以設置 set_rule, unset_rule function,並且 call filter function 之後有根據 function pointer 去 call rule function - Case 2 (5pt) - 加上一條規則: - If source ID is 1, set destination ID to 5 - Case 3 (5pt) - 加上兩條規則: - 1. If source ID is 1, set destination ID to 62. - 2. If source ID is 2, set source ID to 256. - Case 4 (5pt) - 加上下列規則: - 1. If source ID is 1, set destination ID to 5. - 2. If source ID is 2, set source ID to 7. - 3. If size is 2, duplicate data. - 4. If source ID is 7 and destination ID is 3, Drop the packet. 測試之 Code 如下(以Case 4為例),input packet 內容每個 Case 皆相同,想手動測其他 Case 的話改 rule function 跟 set_rule function 就好 :::spoiler fin03.c ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <string.h> #include "firewall.h" typedef int32_t (*RuleFunctionPointer)(const uint8_t *p_input_packet, const int32_t input_size, uint8_t **pp_output_packet, int32_t *p_output_size); // Rule 1: If source ID is 1, set destination ID to 5. int32_t rule1(const uint8_t *p_input_packet, const int32_t input_size, uint8_t **pp_output_packet, int32_t *p_output_size) { if (p_input_packet == NULL || input_size <= 0) { return -1; } *pp_output_packet = (uint8_t *)malloc(input_size * sizeof(uint8_t)); memcpy(*pp_output_packet, p_input_packet, input_size * sizeof(uint8_t)); uint32_t source_id = ((uint32_t *)p_input_packet)[0]; printf("rule1: id: %d\n", source_id); if (source_id == 1) { ((uint32_t *)(*pp_output_packet))[1] = 5; // change destination ID to 5. } *p_output_size = input_size; return 0; } // Rule 2: If source ID is 2, set source ID to 7. int32_t rule2(const uint8_t *p_input_packet, const int32_t input_size, uint8_t **pp_output_packet, int32_t *p_output_size) { if (p_input_packet == NULL || input_size <= 0) { return -1; } *pp_output_packet = (uint8_t *)malloc(input_size * sizeof(uint8_t)); memcpy(*pp_output_packet, p_input_packet, input_size * sizeof(uint8_t)); uint32_t source_id = ((uint32_t *)p_input_packet)[0]; printf("rule2: id: %d\n", source_id); if (source_id == 2) { ((uint32_t *)(*pp_output_packet))[0] = 7; // change destination ID to 7. } *p_output_size = input_size; return 0; } // // Rule 3: If size is 2, duplicate data. int32_t rule3(const uint8_t *p_input_packet, const int32_t input_size, uint8_t **pp_output_packet, int32_t *p_output_size) { if (p_input_packet == NULL || input_size <= 0) { return -1; } uint16_t packet_size = ((uint16_t *)p_input_packet)[4]; printf("rule3: size: %d\n", packet_size); if (packet_size == 2) { *pp_output_packet = (uint8_t*)malloc((input_size + packet_size) * sizeof(uint8_t)); memcpy(*pp_output_packet, p_input_packet, input_size * sizeof(uint8_t)); memcpy(*pp_output_packet + input_size, p_input_packet + input_size - packet_size, packet_size * sizeof(uint8_t)); // duplicate data *p_output_size = input_size + packet_size; } else { *pp_output_packet = (uint8_t *)malloc(input_size * sizeof(uint8_t)); memcpy(*pp_output_packet, p_input_packet, input_size * sizeof(uint8_t)); *p_output_size = input_size; } return 0; } // Rule 4: If source ID is 7 and destination ID is 3, Drop the packet. int32_t rule4(const uint8_t *p_input_packet, const int32_t input_size, uint8_t **pp_output_packet, int32_t *p_output_size) { if (p_input_packet == NULL || input_size <= 0) { return -1; } uint32_t source_id = ((uint32_t *)p_input_packet)[0]; uint32_t destination_id = ((uint32_t *)p_input_packet)[1]; printf("rule4: s_id: %d, d_id: %d\n", source_id, destination_id); if (source_id == 7 && destination_id == 3) { return 1; // drop signal } *pp_output_packet = (uint8_t *)malloc(input_size * sizeof(uint8_t)); memcpy(*pp_output_packet, p_input_packet, input_size * sizeof(uint8_t)); *p_output_size = input_size; return 0; } int main() { uint8_t array[] = { 0x01, 0x00, 0x00, 0x00, // Packet 1 -> Source ID: 1 0x02, 0x00, 0x00, 0x00, // Destination ID: 2 0x03, 0x00, // Size 0x01, 0x02, 0x03, // Data 0x01, 0x00, 0x00, 0x00, // Packet 2 -> Source ID: 1 0x03, 0x00, 0x00, 0x00, // Destination ID: 3 0x02, 0x00, // Size 0xEE, 0xFF, // Data 0x02, 0x00, 0x00, 0x00, // Packet 3 -> Source ID: 2 0x03, 0x00, 0x00, 0x00, // Destination ID: 3 0x04, 0x00, // Size 0x00, 0x00, 0x01, 0x02 // Data }; size_t array_len = sizeof(array)/sizeof(array[0]); uint8_t *inputPacket = malloc(array_len * sizeof(uint8_t)); memcpy(inputPacket, array, array_len); int32_t inputSize = array_len; uint8_t *outputPacket = NULL; int32_t outputSize = 0; printf("rule1: %d\n", set_rule(0, rule1)); printf("rule2: %d\n", set_rule(10, rule2)); printf("rule3: %d\n", set_rule(20, rule3)); printf("rule4: %d\n", set_rule(99, rule4)); printf("filter: %d\n", filter(inputPacket, inputSize, &outputPacket, &outputSize)); uint8_t ans_array[] = { 0x01, 0x00, 0x00, 0x00, // Packet 1 -> Source ID: 1 0x05, 0x00, 0x00, 0x00, // Destination ID: 5 0x03, 0x00, // Size 0x01, 0x02, 0x03, // Data 0x01, 0x00, 0x00, 0x00, // Packet 2 -> Source ID: 1 0x05, 0x00, 0x00, 0x00, // Destination ID: 5 0x04, 0x00, // Size 0xEE, 0xFF, 0xEE, 0xFF // Data }; printf("input_size: %d, output_size: %d\n", inputSize, outputSize); for (int i = 0; i < inputSize; i++) { printf("%d, ", inputPacket[i]); } printf("\n"); for (int i = 0; i < outputSize; i++) { printf("%d, ", outputPacket[i]); } printf("\n"); for (int i = 0; i < sizeof(ans_array)/sizeof(ans_array[0]); i++) { printf("%d, ", ans_array[i]); } printf("\n=============end===========\n"); return 0; } ``` ::: ## 4. The Tank War Game > 助教我很認真的玩了你們寫的遊戲,我花了半天在改這題 測試大小: 20, 40 如果有 Segmentation Fault 或任何不能動的情況我都會多跑幾次你的程式。不會扣分。 詳細回饋請見 Google 表單發還的回饋。 沒有印牆壁 -1 炮口指示標記不會轉動: -3 只有一個電腦玩家會動: -2 如果炮口不會轉動,但有射擊: 1 pt 只動一步就死了: 後面分數也拿不到