//p43.c ---Pascal Triangle & C(n, m) (注意這改叫 n 取 m)
// @CopyLeft by tsaiwn@cs.nctu.edu.tw
// remind you that 要善用立委工程轉包概念
// we write a function can read一個int或兩個int整數的 getNM( );
// 它會幫忙讀取一個或兩個整數; 可能一個, 也可能兩個; 用途不同 !
/// 建議同學們仔細研究該 function getNM( )
/// 印出 n 階 Pascal triangle, 或是 印出 C(n, m) 即 n 取 m 的答案 !
#define N_MAX 100
#include <stdio.h>
#include <stdlib.h>
long getNM(void);  // 先宣告(聲明)會寫一個 long getNM( ) function 
  //因為還沒教到如何透過參數回傳值, 若輸入兩數n,m就回傳 n*1000 + m
void pascal(int, int);  // 聲明會寫一個 "兩參數" function 叫做 pascal 
int main( ) {   // 大多數 main program 都這樣開頭
   int n, m;  //  注意 n, m 都是 int, 不是 long 喔! 與之前範例不同!
   long tmp; // temporary long integer  
    while(49==49) {   //   (注意)  可以改用別的方法做 Loop
        printf("Input n for PascalTriangle; 或 n, m for C(n,m): ");
        tmp = getNM(  );   // 寫成函數 (function; 函式) 是個很好的習慣;
        if( tmp < 0 ) break;   //  若是負數就停 ! (注意) 可以改用別的方法;
        n = tmp/1000; m=tmp%1000;
        if(n > N_MAX) {  // 防呆 !  important !
            printf(" %d too Large! should be in 1..%d\n", n, N_MAX);
            continue;  // 繼續下一回合 (next pass)
        } //
        if(m == 0) m = -1;  // -1 means find C(n, m)
        pascal(n, m);  // m == -1 表示印出巴斯卡三角形!
        /// ==> 注意, 這樣我們就不支援 C(??, 0) 因為 m 不可是 0 
    } // while  
    printf("Bye bye!\nHit RETURN key ..."); 
    getchar( );  // 企圖讀取一個 char, 讓程式停著等 User 按 RETURN 鍵;
    return  0;    //   告知作業系統(OS)表示我們這主程式正常結束
}// main(
long getNM( ) {   // 以後要改輸入的方法只要改這 function 就可 :-)
    //因為還沒教到如何透過參數回傳值, 若輸入兩數n,m就回傳 n*1000+m
    long ans, n, m;  // Local variables
    static char buf[99];   // a string buffer for input;  why "static" ?
    buf[0]=0; // clear the string
    fgets(buf, sizeof(buf), stdin); //stdin 就是鍵盤, 宣告在 <stdio.h>
    ans = sscanf(buf, "%d, %d", &n, &m); // first try ?,?
    if(ans <= 1) ans = sscanf(buf, "%d %d", &n, &m); // 2nd try ? ?
    if(ans == 1) ans = n*1000;   // We ONLY got one number
    else if(ans == 2) ans = n*1000+m;
    else ans = 0;  // got nothing
    return ans;
}
void pascal(int n, int m) {   // 若 m == -1 表示要巴斯卡三角形
    int i, k;  // for Loop
    //..  先把九九乘法表的程式研究清楚對此題會略有幫助 
   static long long x[N_MAX+1]; // 注意改用 long long; one-dimension
    for(i = 0; i <= n; ++i) {
        x[0] = x[i] = 1;  // 最左最右都填 1
        for(k= i-1; k >= 1; --k) {  // 由右而左 從 i-1 到 1 叫做中間!
           x[k] = x[k] + x[k-1]; // 自己 + 左邊 ;
        } // for k
        if(m == -1) {  // 要印 Pascal Triangle
            for(k=0; k<= 3*(n-i); ++k) printf(" ");
            for(k=0; k <= i; ++k) printf("%5d ", x[k]);
            printf("\n");
        }// if(m
    } // for(i
    if(m != -1) {  //  means find C(n, m)
        printf(" C(%d, %d) = %I64d\n", n, m, x[m]);  //有些 %lld
        // 想一想何以 C(n, m) 的答案在 x[m]  ???
    } // for C(n, m)
}// pascal 
// 關於 Pascal Triangle 程式, 請參考本課程給的投影片內說明!
// 還不會的先練習印出所有 1 到 n 的奇數 (Hint:  k%2 !=0 則 k 就是奇數)
// 如果你有 K&R 課本, 可研究課本內討論 atoi 與 atof 函數是如何寫的,
// 可以讓你增加功力喔 !
/***************************

D:\LABs>gcc p43.c

D:\LABs>a.exe
Input n for PascalTriangle; 或 n, m for C(n,m): 999
 999 too Large! should be in 1..100
Input n for PascalTriangle; 或 n, m for C(n,m): 3
              1
           1     1
        1     2     1
     1     3     3     1
Input n for PascalTriangle; 或 n, m for C(n,m): 5
                    1
                 1     1
              1     2     1
           1     3     3     1
        1     4     6     4     1
     1     5    10    10     5     1
Input n for PascalTriangle; 或 n, m for C(n,m): 200,3
 200 too Large! should be in 1..100
Input n for PascalTriangle; 或 n, m for C(n,m): 100,2
 C(100, 2) = 4950
Input n for PascalTriangle; 或 n, m for C(n,m): 100,3
 C(100, 3) = 161700
Input n for PascalTriangle; 或 n, m for C(n,m): 7
                          1
                       1     1
                    1     2     1
                 1     3     3     1
              1     4     6     4     1
           1     5    10    10     5     1
        1     6    15    20    15     6     1
     1     7    21    35    35    21     7     1
Input n for PascalTriangle; 或 n, m for C(n,m): 100,5
 C(100, 5) = 75287520
Input n for PascalTriangle; 或 n, m for C(n,m): 100,6
 C(100, 6) = 1192052400
Input n for PascalTriangle; 或 n, m for C(n,m): 100,7
 C(100, 7) = 16007560800
Input n for PascalTriangle; 或 n, m for C(n,m): 100,8
 C(100, 8) = 186087894300
Input n for PascalTriangle; 或 n, m for C(n,m): 100,9
 C(100, 9) = 1902231808400
Input n for PascalTriangle; 或 n, m for C(n,m): 100,10
 C(100, 10) = 17310309456440
Input n for PascalTriangle; 或 n, m for C(n,m): 100, 90
 C(100, 90) = 17310309456440
Input n for PascalTriangle; 或 n, m for C(n,m): 100 12
 C(100, 12) = 1050421051106700
Input n for PascalTriangle; 或 n, m for C(n,m): 100 88
 C(100, 88) = 1050421051106700
Input n for PascalTriangle; 或 n, m for C(n,m): 100 100
 C(100, 100) = 1
Input n for PascalTriangle; 或 n, m for C(n,m): 100,100
 C(100, 100) = 1
Input n for PascalTriangle; 或 n, m for C(n,m): -1
Bye bye!
Hit RETURN key ...

D:\LABs>
*******************************************/
