# HW05 參考答案 ## 5.1 Statistics :::spoiler mystatistics.c ```c int32_t statistics(int32_t *pData, int32_t size, double *pMean, double *pVariance, double *pStd) { if (pData == NULL || size <= 0 || pMean == NULL || pVariance == NULL || pStd == NULL) { return -1; // Invalid input } double sum = 0; for (int32_t i = 0; i < size; i++) { sum += pData[i]; } *pMean = sum / size; double varSum = 0; for (int32_t i = 0; i < size; i++) { varSum += (pData[i] - *pMean) * (pData[i] - *pMean); } *pVariance = varSum / size; *pStd = sqrt(*pVariance); return 0; // Success } ``` ::: ## 5.2 Gaussian Elimination The following code are revised from the code written by 41247024S 廖妤恩: :::spoiler myge.h ```c= #ifndef MYGE_H #define MYGE_H #include <stdint.h> int32_t gaussian_elimination(int32_t n, int32_t *pA, int32_t *py, int32_t **px); #endif // MYGE_H ``` ::: :::spoiler myge.c ```c= #include "myge.h" #include <stdio.h> #include <stdlib.h> #include <math.h> int32_t gaussian_elimination(int32_t n, int32_t *pA, int32_t *py, int32_t **px) { // Check for null pointers and non-positive matrix size if ( pA == NULL || py == NULL ) return -1; if ( n <= 0 ) return -1; // Initialize augmented matrix for Gaussian elimination int32_t aM[n][n+1]; // augmented matrix for ( int i = 0 ; i < n ; i ++ ){ for ( int j = 0 ; j < n ; j ++ ){ aM[i][j] = 0; } } for ( int i = 0 ; i < n ; i ++ ){ for ( int j = 0 ; j < n ; j ++ ){ aM[i][j] = *(pA+i*n+j); } } for ( int i = 0 ; i < n ; i ++ ){ aM[i][n] = *(py+i); } double eM[n][n+1]; // elimination matrix for ( int i = 0 ; i < n ; i ++ ){ for ( int j = 0 ; j < n + 1 ; j ++ ){ eM[i][j] = aM[i][j]; } } for ( int i = 0 ; i < n ; i ++ ){ if ( eM[i][i] == 0 ){ for ( int j = 0 ; j < n + 1 ; j ++ ){ int32_t temp = eM[i][j]; eM[i][j] = eM[i+1][j]; eM[i+1][j] = temp; } } } for ( int time = 0 ; time < n ; time ++ ){ for ( int i = time + 1 ; i < n ; i ++ ){ if ( eM[i][time] == 0 || eM[time][time] == 0 ) continue; double multi = -eM[i][time]/eM[time][time]; for ( int j = 0 ; j < n + 1 ; j ++ ){ eM[i][j] = eM[i][j] + eM[time][j]*multi; } } } for ( int i = 0 ; i < n ; i ++ ){ int32_t noans = 0; for ( int j = 0 ; j < n ; j ++ ){ noans += eM[i][j]; } if ( noans == 0 && eM[i][n] != 0 ) return 0; if ( noans == 0 && eM[i][n] == 0 ) return 2; } //to 1 for ( int i = 0 ; i < n ; i ++ ){ double divi = eM[i][i]; for ( int j = 0 ; j < n + 1 ; j ++ ){ eM[i][j] /= divi; } } for ( int i = n - 1 ; i >= 0 ; i -- ){ double chen = eM[i][i]; if ( chen == 0 ) continue; for ( int j = 0 ; j < n ; j ++ ){ eM[i][j] /= chen; } for ( int k = i-1 ; k >= 0 ; k -- ){ double fac = eM[k][i]; if ( fac == 0 ) continue; for ( int j = 0 ; j < n+1 ; j ++ ){ eM[k][j] -= fac*eM[i][j]; } } } for ( int i = 0 ; i < n ; i ++ ){ int32_t noans = 0; for ( int j = 0 ; j < n ; j ++ ){ noans += eM[i][j]; } if ( noans == 0 && eM[i][n] != 0 ) return 0; if ( noans == 0 && eM[i][n] == 0 ) return 2; } int32_t ans[n]; for ( int i = 0 ; i < n ; i ++ ) ans[i] = 0; for ( int i = 0 ; i < n ; i ++ ){ ans[i] = (int) round ( eM[i][n]/eM[i][i] ); } *px = malloc ( n*sizeof(int) ); for ( int i = 0 ; i < n ; i ++ ){ *(*px+i) = ans[i]; } return 1; } ``` ::: ## 5.3 Sphere :::spoiler mysphere.h ```c #pragma once #include <stdint.h> #include <math.h> #include <stdio.h> // Return -1 if the inputs are invalid. // Return 0 if no such a plane. // Otherwise, Return 1. int32_t get_cap_area( double r, double a, double b, double c, double d, double *pArea ); ``` ::: :::spoiler mysphere.c ```c #include "mysphere.h" int32_t get_cap_area( double r, double a, double b, double c, double d, double *pArea ) { if (pArea == NULL) { return -1; } if (r <= 0 || (a == 0 && b == 0 && c == 0)) { return -1; } double h = fabs(d) / sqrt(a * a + b * b + c * c) ; if (h >= r) { return 0; } *pArea = M_PI * (r * r - h * h); return 1; } ``` ::: ## 5.4 TLV Credit: 41247022S 林O恩 :::spoiler `mytlv.c` ```c= #include <math.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> int32_t run(uint8_t *pByteArray, int32_t size); static int32_t get_length(uint8_t *pByteArray, int32_t size, int32_t byte); static int32_t get_value(uint8_t *pByteArray, int32_t size, int32_t byte, int32_t length); static int32_t TLV(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t skip(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV1(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV2(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV3(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV4(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV5(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV6(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV7(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV8(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV9(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t TLV10(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number); static int32_t (*TLVtype[11])(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) = {skip, TLV1, TLV2, TLV3, TLV4, TLV5, TLV6, TLV7, TLV8, TLV9, TLV10}; static int8_t is_cancel(uint8_t *pByteArray, int32_t size, int32_t byte); static uint64_t save = 0; int8_t set_number = -1, set_save = -1; int32_t run(uint8_t *pByteArray, int32_t size) { if (pByteArray == NULL) { return -1; } static uint64_t number = 0; set_number = -1; set_save = -1; save = 0; int32_t byte = 0; while (byte < size) { byte = TLV(pByteArray, size, byte, &number); if (byte == -1) { return -1; } // fprintf(stderr,"%lu\n", number); } return 0; } static int32_t get_length(uint8_t *pByteArray, int32_t size, int32_t byte) { int32_t length = 0; if (size < byte + 3) { return -1; } length = pByteArray[byte + 1] + pByteArray[byte + 2] * 256; ///// return length; } static int32_t get_value(uint8_t *pByteArray, int32_t size, int32_t byte, int32_t length) { uint64_t value = 0; if (size < byte + 3 + length) { return -1; } for (int32_t i = 0; i < length; i++) { value = value * 10 + pByteArray[byte + 3 + i]; } return value; } static int32_t TLV(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { if (pByteArray[byte] > 10) { return TLVtype[0](pByteArray, size, byte, p_number); } else { return TLVtype[pByteArray[byte]](pByteArray, size, byte, p_number); } } static int32_t skip(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { save = *p_number; int32_t length = get_length(pByteArray, size, byte); // uint64_t value = get_value(pByteArray, size, byte, length); return (byte + 3 + length); } static int32_t TLV1(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = value int32_t length = get_length(pByteArray, size, byte); uint64_t value = get_value(pByteArray, size, byte, length); save = *p_number; set_save = set_number; set_number = 1; *p_number = value; return (byte + 3 + length); } static int32_t TLV2(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number += value if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); uint64_t value = get_value(pByteArray, size, byte, length); set_save = set_number; set_number = 1; save = *p_number; *p_number += value; return byte + 3 + length; } static int32_t TLV3(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number *= value if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); uint64_t value = get_value(pByteArray, size, byte, length); set_save = set_number; set_number = 1; save = *p_number; *p_number *= value; return byte + 3 + length; } static int32_t TLV4(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = number / 2 // only length = 0 if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); // uint64_t value = get_value(pByteArray, size, byte, length); if (length != 0) { return -1; } set_save = set_number; set_number = 1; save = *p_number; *p_number /= 2; return byte + 3; } static int32_t TLV5(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = number /10 // only length = 0 if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); // uint64_t value = get_value(pByteArray, size, byte, length); if (length != 0) { return -1; } set_save = set_number; set_number = 1; save = *p_number; *p_number /= 10; return byte + 3; } static int32_t TLV6(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = value || number if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); uint64_t value = get_value(pByteArray, size, byte, length); save = *p_number; int32_t n_digit = 0; if (*p_number == 0) n_digit = 1; else n_digit = (int32_t)log10(*p_number) + 1; for (int32_t i = 0; i < n_digit; i++) { value *= 10; } set_save = set_number; set_number = 1; *p_number += value; return byte + 3 + length; } static int32_t TLV7(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = number || value if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); uint64_t value = get_value(pByteArray, size, byte, length); set_save = set_number; set_number = 1; save = *p_number; int32_t n_digit = 0; if (value == 0 && length != 0) n_digit = 1; else if (value == 0 && length == 0) n_digit = 0; else n_digit = (int32_t)log10(value) + 1; for (int32_t i = 0; i < n_digit; i++) { *p_number *= 10; } *p_number += value; return byte + 3 + length; } static int32_t TLV8(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = init to 0 // only length = 0 int32_t length = get_length(pByteArray, size, byte); if (length != 0) { return -1; } set_save = set_number; set_number = 1; save = *p_number; *p_number = 0; return byte + 3; } static int32_t TLV9(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // number = print number // only length = 0 if (set_number == -1) return -1; int32_t length = get_length(pByteArray, size, byte); if (length != 0) { return -1; } set_save = set_number; save = *p_number; if (!is_cancel(pByteArray, size, byte)) // printf("%lu\n", *p_number); return byte + 3; } static int32_t TLV10(uint8_t *pByteArray, int32_t size, int32_t byte, uint64_t *p_number) { // cancel previous TLV // only length = 0 if (byte == 0 && is_cancel(pByteArray, size, byte - 3)) { return -1; } int32_t length = get_length(pByteArray, size, byte); if (length != 0) { return -1; } int32_t temp = 0; temp = *p_number; *p_number = save; save = temp; temp = set_number; set_number = set_save; set_save = temp; return byte + 3; } int8_t is_cancel(uint8_t *pByteArray, int32_t size, int32_t byte) { int32_t next = 0; next = byte + 3; if (next >= size) { return 0; } int32_t cancel = 0; while (*(pByteArray + next) == 10 && *(pByteArray + next + 1) == 0 && *(pByteArray + next + 2) == 0) { if (cancel == 0) { cancel = 1; } else { cancel = 0; } next += 3; if (next >= size) { break; } } return cancel; } ``` ::: ## 5.5 TAS Editor :::spoiler tas.c ```c #include <stdint.h> #include <stdlib.h> #include <stdbool.h> #include <stdio.h> void button_set_frame(uint8_t **src, size_t *size, const uint8_t button, const uint64_t start_frame, const uint64_t end_frame) { // end frame overflow issue, realloc src if(end_frame >= *size) { *src = (uint8_t*)realloc(*src, (end_frame + 1) * sizeof(uint8_t)); for (int i = *size; i <= end_frame; i++) { (*src)[i] = 0; } *size = end_frame + 1; } // set button to src for (int i = 0; i < *size; i++) { if(i >= start_frame && i <= end_frame) { (*src)[i] |= button; } } } void button_unset_frame(uint8_t *src, const size_t size, const uint8_t button, const uint64_t start_frame, const uint64_t end_frame) { // unset button to src for (int i = 0; i < size; i++) { if(i >= start_frame && i <= end_frame) { src[i] = src[i] & (~button); } } } ``` ::: ## 5.6 Bonus: What is Wrong? 下圖是 41247009S 蘇同學畫的圖: 其中 M 欄的單位是 1 byte ![image](https://hackmd.io/_uploads/SJj0c7lO6.png) 上圖解釋了為什麼答案會是 `5 0 0 0 0`。 而 What will happen if the size is five? 則是會 Segmentation Fault。可以看到 N 欄深藍色就是 size 為 5 的情況,第一步就已經超出去了。所以開 size = 6 就可以解決這個問題。