HW03 評分標準

3.1 Circle Functions

整題扣分項目:

  1. #include "mycircle.h" 在第一行會導致無法編譯(Wrong Header): -4 pts(扣 4 分而已)
    老師上課有說過,header 裡面用了什麼其他 header file,要自己 include。可以參考 https://www.youtube.com/live/7nyTntpXVFk?si=2LuseUUToNuiaESH&t=3373
檢測 header 用的 hw0301.c

如果以下程式編譯出現 error,將會扣分

#include "mycircle.h"


int main(){
    return 0;
}

Subtask 1(10 pts)

子任務說明: 測試 function 功能是否正確,無回傳負值

Subtask 2(10 pts)

子任務說明: 各種奇怪的操作,需要回傳負值

hw0301.c
#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include "mycircle.h"


#define PI acos(-1)
#define eps 1e-6

double ans_r = -1;
int32_t ans_set_radius( double r);
double ans_circle_circumference();
double ans_circle_area();
double ans_tangent_area( double x );
double ans_inner_regular_polygon_area( int32_t n );
double ans_outer_regular_polygon_area( int32_t n );

double subtask1(){
    int total_score = 0;
    int score = 0;
    double arr_r[] = {16, 0.15, 10000, 0.001};
    for(int i = 0; i < 4; i++){
        double r = arr_r[i];

        if(set_radius(r) == ans_set_radius(r)){
            score += 4;
        }else{
            //printf("set_radius(%lf) != ans_set_radius(%lf)\n", r, r);
        }
        total_score += 4;

        if((ans_circle_circumference() < 0 && (get_circle_circumference() < 0)) || fabs(get_circle_circumference() - ans_circle_circumference()) < eps){
            score += 4;
        }else{
            //printf("get_circle_circumference() != ans_circle_circumference()\n");
        }
        total_score += 4;

        if((ans_circle_area() < 0 && (get_circle_area() < 0)) || fabs(get_circle_area() - ans_circle_area()) < eps){
            score += 4;
        }else{
            //printf("get_circle_area() != ans_circle_area()\n");
        }
        total_score += 4;

        for(int j = 1; j < 9; j++){
            double x = (-r) + (2 * r / 9) * j;
            if((ans_tangent_area(x) < 0 && (get_tangent_area(x) < 0)) || fabs(get_tangent_area(x) - ans_tangent_area(x)) < eps){
                score++;
            }else{
                //printf("r = %lf\n", r);
                //printf("get_tangent_area(%lf): %lf\n", x, get_tangent_area(x));
                //printf("ans_tangent_area(%lf): %lf\n", x, ans_tangent_area(x));
            }
            total_score++;
        }

        int32_t arr_n[] = {3, 4, 8, 2023, 11, 9};
        for(int j = 0; j < 6; j++){
            int32_t n = arr_n[j];
            if((ans_inner_regular_polygon_area(n) < 0 && (get_inner_regular_polygon_area(n) < 0)) || fabs(get_inner_regular_polygon_area(n) - ans_inner_regular_polygon_area(n)) < eps){
                score++;
            }else{
                //printf("r = %lf\n", r);
                //printf("get_inner_regular_polygon_area(%d): %lf\n", n, get_inner_regular_polygon_area(n));
                //printf("ans_inner_regular_polygon_area(%d): %lf\n", n, ans_inner_regular_polygon_area(n));
            }
            total_score++;
        }
        for(int j = 0; j < 6; j++){
            int32_t n = arr_n[j];
            if((ans_outer_regular_polygon_area(n) < 0 && (get_outer_regular_polygon_area(n) < 0)) || fabs(get_outer_regular_polygon_area(n) - ans_outer_regular_polygon_area(n)) < eps){
                score++;
            }else{
                //printf("r = %lf\n", r);
                //printf("get_outer_regular_polygon_area(%d): %lf\n", n, get_outer_regular_polygon_area(n));
                //printf("ans_outer_regular_polygon_area(%d): %lf\n", n, ans_outer_regular_polygon_area(n));
            }
            total_score++;
        }
    }
    return (double)score / total_score * 10;
}

double subtask2(){
    int total_score = 0;
    int score = 0;

    // call other functions before calling set_radius()
    score += (get_circle_circumference() < 0) + (get_circle_area() < 0) + (get_tangent_area(0.4) < 0) + (get_inner_regular_polygon_area(3) < 0) + (get_outer_regular_polygon_area(3) < 0);
    total_score += 5;
    //printf("score = %d, total_score = %d\n", score, total_score);

    // set_radius() is invalid
    score += (set_radius(-1) == ans_set_radius(-1));
    total_score++;
    //printf("score = %d, total_score = %d\n", score, total_score);

    // get_tangent_area() is invalid
    set_radius(1);
    ans_set_radius(1);
    score += (get_tangent_area(1) < 0) + (get_tangent_area(-1) < 0) + (get_tangent_area(0) < 0);
    total_score += 3;
    //printf("score = %d, total_score = %d\n", score, total_score);

    // get_xxx_regular_polygon_area() is invalid
    score += (get_inner_regular_polygon_area(2) < 0) + (get_outer_regular_polygon_area(2) < 0);
    total_score += 2;
    //printf("score = %d, total_score = %d\n", score, total_score);

    // set_radius() is invalid, revert to the previous radius
    score += (set_radius(-1) == ans_set_radius(-1));
    score += (fabs(get_circle_area() - ans_circle_area()) < eps) +(fabs(get_circle_circumference() - ans_circle_circumference()) < eps);
    total_score += 3;
    //printf("score = %d, total_score = %d\n", score, total_score);

    return (double)score / total_score * 10;
}

int main(){

    double score = 0;
    double s1, s2;
    s2 = subtask2();
    score += s2;
    //printf("Subtask 2 score: %lf\n", s2);
    s1 = subtask1();
    score += s1;
    printf("\n");
    printf("subtask1: %lf + subtask2: %lf = %lf\n", s1,s2, score);
    printf("%d\n", (int)score);

    return 0;
}


// Setup the radius r of the circle.
// This function must be called before all other functions.
// If r <= 0, return -1; otherwise , return 0.
int32_t ans_set_radius( double r){
    if(r <= 0){
        return -1;
    }
    ans_r = r;
    return 0;
}

// Return the circumference of the circle
// If the radius is not set, return a negative number.
double ans_circle_circumference(){
    return ans_r < 0 ? -1 : 2 * PI * ans_r;
}


// Return the area of the circle
// If the radius is not set, return a negative number.
double ans_circle_area(){
    return ans_r < 0 ? -1 : PI * ans_r * ans_r;
}


// Given x, (x,y) is a point on the upper circle.
// Return the area bounded by the tangent line at (x,y), x-axis and y-axis.
// If the radius is not set, return a negative number.
// If it cannot form a triangle , return a negative number.
// If x is not a reasonable input , return a negative number.
double ans_tangent_area( double x ){
    if(ans_r < 0 || x > ans_r){
        return -1;
    }
    double y = sqrt(ans_r * ans_r - x * x);

    // is horizontal or vertical line
    if(fabs(x-ans_r) < eps || fabs(y-ans_r) < eps){
        return -1;
    }
    // calculate the tangent line
    double m = -x / y;
    double b = y - m * x;

    // calculate the intersection of the tangent line and x-axis
    double x1 = -b / m;

    // calculate the intersection of the tangent line and y-axis
    double y1 = b;

    // calculate the area of the triangle
    double area = fabs(x1) * fabs(y1) / 2;

    return area;
}

// Return the inner regular polygon area.
// If the radius is not set, return a negative number.
// If n < 3, return a negative number.
double ans_inner_regular_polygon_area( int32_t n ){
    if(ans_r < 0 || n < 3){
        return -1;
    }
    // (360/n) * (PI/180) = (2*PI/n)
    double theta = 2 * PI / n;
    double area = n * ans_r * ans_r * sin(theta) / 2;
    return area;
}

// Return the outer regular polygon area.
// If the radius is not set, return a negative number.
// If n < 3, return a negative number.
double ans_outer_regular_polygon_area( int32_t n ){
    if(ans_r < 0 || n < 3){
        return -1;
    }
    
    double theta = 2 * PI / n;
    double r = ans_r / cos(theta / 2);
    double area = n * r * r * sin(theta) / 2;
    return area;
}

3.2 Control Game Character

hw0302
#include "mycontrol.h"
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

// score 4
void return_value_test() {
  int32_t test_passed = 4;
  if (forward(1) != -1) {
    test_passed--;
  }
  if (clock_turn(1) != -1) {
    test_passed--;
  }
  if (counterclock_turn(1) != -1) {
    test_passed--;
  }
  if (print() != -1) {
    test_passed--;
  }
  printf("%d\n", test_passed);
  return;
}

// score 3
void initialize_test() {
  initialize(0, 0, M_PI * 21.5);
  print();

  initialize(999.994, -999.995, -M_PI * 21.5);
  print();

  initialize(-999.999, 999.995, 0);
  print();
}

// score 3
void forward_test() {
  initialize(2.5, -1.5, M_PI / 3);
  forward(1.5);
  print();

  initialize(2.5, -1.5, -M_PI / 4);
  forward(-3.8);
  print();

  initialize(-6.1, -2.9, M_PI / 2);
  forward(-4.7);
  print();
}

// score 3
void turn_test() {
  initialize(2.5, -1.5, M_PI / 3);
  clock_turn(M_PI / 4);
  print();

  initialize(2.5, -1.5, -M_PI / 4);
  counterclock_turn(M_PI * 3 / 4);
  print();

  initialize(-6.1, -2.9, M_PI / 2);
  clock_turn(-M_PI * (2.0 + 1.0 / 3.0));
  print();
}

// score 2
void multi_test1() {
  initialize(0, 0, 0);
  forward(1);
  clock_turn(M_PI / 2);
  forward(1);
  counterclock_turn(M_PI / 2);
  forward(1);
  clock_turn(M_PI / 2);
  forward(1);
  print();
}

// score 2
void multi_test2() {
  initialize(0, 0, 0);
  forward(-100);
  clock_turn(-M_PI * 3.14159);
  forward(99);
  counterclock_turn(-M_PI * 31.4159);
  forward(-31);
  print();
}

// score 3
void recurrsion_test(int8_t deep) {
  if (deep == 0) {
    print();
    return;
  }
  clock_turn(M_PI / 4);
  forward(deep);
  recurrsion_test(deep - 1);
  forward(-deep);
  counterclock_turn(M_PI / 2);
  forward(deep);
  recurrsion_test(deep - 1);
  clock_turn(M_PI / 4);
  forward(-deep);
  return;
}
int main() {
  return_value_test();
  initialize_test();
  forward_test();
  turn_test();
  multi_test1();
  multi_test2();
  initialize(0, 0, 0);
  recurrsion_test(3);

  return 0;
}
Ans
// return val test
4
// iniialize test
position: (0.00,0.00), angle: 1.50
position: (999.99,-1000.00), angle: 0.50
position: (-1000.00,1000.00), angle: 0.00
// forward test
position: (3.25,-0.20), angle: 0.33
position: (-0.19,1.19), angle: 1.75
position: (-6.10,-7.60), angle: 0.50
// turn test
position: (2.50,-1.50), angle: 0.08
position: (2.50,-1.50), angle: 0.50
position: (-6.10,-2.90), angle: 0.83
// multi_test1
position: (2.00,-2.00), angle: 1.50
// multi_test2
position: (-209.55,-19.07), angle: 1.73
// recurrstion test
position: (1.41,-4.83), angle: 1.25
position: (2.83,-4.83), angle: 1.75
position: (5.54,-2.54), angle: 1.75
position: (5.54,-1.12), angle: 0.25
position: (5.83,3.83), angle: 1.75
position: (5.83,5.24), angle: 0.25
position: (3.54,7.95), angle: 0.25
position: (2.12,7.95), angle: 0.75

3.3 Binary Form

2pt for each case

Case1

0

Case2

1

Case3

-1

Case4

2024

Case5

-2023

Case6

20231116

Case7

-20231116

Case8

-111111111

Case9

2147483647

Case10

-2147483648

3.4 Tower of Hanoi

共有 6 筆測試,iterative 與 resursive 各 3 筆,皆為 2、6、20。
詳細測試可參考:https://github.com/JacobLinCool/cpta/tree/main/examples/2023-fall/hw0304/.cases

其中 LLMSourceCheck 後來沒用到

3.5 How to roll your dice SE (Simple Edition)?

分數配分:
(1d6, AdX, AdXkY+B, AdXkhHklLkcC+B, additional roll feat, input, cool name, UI/UX, Anything)
(4, 4, 4, 4, 2, 2, 1, 2, 0+)

1d6: 實作 1d6
AdX: 實作 AdX
AdXkY+B: 實作 AdXkY+B
AdXkhHklLkcC+B: 實作 AdXkhHklLkcC+B
additional roll feat: 實作額外骰子功能及有寫在 README 上
input: 任意輸入正確
cool name: 有取除了範例以外的名字
UI/UX: 使用順暢、美觀程度
Anything: 任何有於 README 上的巧思及錯誤扣分

3.6 Bonus: diff and patch

3.7 Bonus: Plagiarism Detection

如有聲明,使用 AI 輔助不構成扣分條件,否則以 1 分計。

評分取決於對內容指紋產生(k-gram, hashing)與選擇(winnowing)之敘述。