嘗試用C語言解題

BUG fix :

W:槽的SciTE有點小問題,因為設定檔是從Y:複製來的,所以需要重新定義TinyC的位置。

只要修改cpp.properties的路徑就可以了。


Nutcracker Solution :

上學期的Nutcracker網誌內容

之前的python題目,稍微研究一下後轉成C語言。

不過如果直接運行會跑很久。但是這裡可以練習一下小型演算法的模式。

先做了兩個程式,不過第一是介面而已,第二個才是主要架構。

撰寫的途中使用Solvespace研究,由於數學邏輯不太好,很多幾何的東西沒那麼直觀。

有時候會偷吃步測試一些解法。

第二支程式是從python的範例改來的,不過後來做了很多變化,只有解最小路徑最大角度。

演算法概念:

途中查了很多數學公式,無奈常常打錯又不知道正確性,重複試了很多次才成功。

#include 
#include 

int k=40;
int h=10;
int a=40;
int b=80;
double r=10;
double pi=M_PI;
int num=1000;

int main()
{
    double deg =pi/180;
    for (int j=45*num; j<=180*num; j++){
        double num0=num;
        double th=j/num0*deg;
        double x1=a*cos(th);
        double y1=a*sin(th);
        double x2=x1+sqrt(b*b-y1*y1);
        double m=tan(th);
        double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1));
        printf("%g\n", (int)(j/num0*100000+.5)/100000.);
        if(r1<=r){
            printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m);
            break;
        }
    }
    return 0;
}

第二支程式的最後成果。

最後精確度還是沒有很高,不知道問題出在哪裡。

第一支程式是剛開始寫輸入端介面,供使用者輸入自訂參數,後來再把第二支程式的模型搬回來用,並另外寫一個解最大路徑和最小角度的程式,所有例外狀況也是在這裡排除。

後來還不知道怎麼讓副程式傳回double或其他浮點數,查一下才知道要在開始前宣告一次。

#include 
#include 

int a, b, k, h, r, lim;
double o, wp, thmin, thmax;
double pi=M_PI;
int num=1000;

double solve_minpath(int, int, int, int, int);
double solve_maxangle(int, int, int, int, int);
double solve_maxpath(int, int, int, int);
double solve_minangle(int, int, int, int);

int main()
{
    scanf("%d,%d,%d,%d,%d,%d", &a, &b, &k, &h, &r, &lim);
//強制正值
    a=abs(a);
    b=abs(b);
    h=abs(h);
    k=abs(k);
    r=abs(r);
    lim=abs(lim);
    printf("\n---\n");
    printf("Used pi= %f\n", pi);
    printf("---\n");
    printf("Connecting Rod:\n");
    printf("a= %d b= %d\n", a, b);
    printf("Rod radius= %d\n", r);
    printf("Rod width= %d\n", r*2);
    printf("Space Usage:\n");
    printf("h= %d k= %d\n", h, k);
    printf("Work Path= %d\n", lim);
    printf("---\n\n");
//相關參數代入副程式解題
    o=solve_minpath(k, h, a, b, r);
    wp=solve_maxpath(lim, a, b, r)-o;
    thmin=solve_minangle(lim, a, b, r);
    thmax=solve_maxangle(k, h, a, b, r);
    if(a*b*lim==0){
        printf("---ERRO---\nSome value can't be zero.\n");
        return 1;
    }
    else{
        if(o+r>lim){
            printf("---ERRO---\nSpace is not enough.\n");
            return 2;
        }
        else{
            printf("\n---\n---Result---\n");
            printf("Distance:\n");
            printf("Offset distance:\n");
            printf("o= %f\n", o);
            printf("Work distance:\n");
            printf("wp= %f\n", wp);
            printf("Angle(Degree):\n");
            printf("min= %f max= %f\n---\n", thmin, thmax);
            return 0;
        }
    }
}

double solve_minpath(int k, int h, int a, int b, int r)
{
    double deg =pi/180;
    for (int j=45*num; 180*num>=j; j++){
        double num0=num;
        double th=j/num0*deg;
        double x1=a*cos(th);
        double y1=a*sin(th);
        double x2=x1+sqrt(b*b-y1*y1);
        double m=tan(th);
        double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1));
        if(r>=r1){
            printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m);
            return x2;
            break;
        }
    }
    return 0;
}

double solve_maxangle(int k, int h, int a, int b, int r)
{
    double deg =pi/180;
    for (int j=45*num; 180*num>=j; j++){
        double num0=num;
        double th=j/num0*deg;
        double x1=a*cos(th);
        double y1=a*sin(th);
        double x2=x1+sqrt(b*b-y1*y1);
        double m=tan(th);
        double r1=abs((x2-x1)*(h-y1)-(0-y1)*(k/2-x1))/sqrt(y1*y1+(x2-x1)*(x2-x1));
        if(r>=r1){
            printf("(%f,%f) (%f,0)\n%f\n%f r=%f\nm=%f\n", x1, y1, x2, th/deg, r, r1, m);
            return th/deg;
            break;
        }
    }
    return 0;
}

double solve_maxpath(int lim, int a, int b, int r)
{
    double n;
    double th;
    if (lim>a+b+r){
        n=a+b;
        th=0;
    }
    else{
        n=lim-r;
        th=acos((a*a+n*n-b*b)/2*a*n);
    }
    return n;
}

double solve_minangle(int lim, int a, int b, int r)
{
    double n;
    double th;
    if (lim>a+b+r){
        n=a+b;
        th=0;
    }
    else{
        n=lim-r;
        th=acos((a*a+n*n-b*b)/(2*a*n));
    }
    return th;
}

最後執行的結果:


剛開始還以為是用公式推導座標點的結果,後來回去看網誌才知道用演算法計算。電腦演算時如果一邊列出結果,會拖慢速度,所以在最後的程式碼中只留檢查用的結果。

後來也有上網看其他人使用基因演算法的案例,未能完全了解,還有很多要學習的地方。這次解題複習了一些C語言的概念,希望在往後利用上能夠駕輕就熟。


Comments

comments powered by Disqus