# 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

上圖解釋了為什麼答案會是 `5 0 0 0 0`。
而 What will happen if the size is five? 則是會 Segmentation Fault。可以看到 N 欄深藍色就是 size 為 5 的情況,第一步就已經超出去了。所以開 size = 6 就可以解決這個問題。