# 家教解答 題目: https://docs.google.com/document/d/1xcLkz2zezrbLb0pE_CQ8v7b5vDbvAWhlKsktEUtHDpw/edit?usp=sharing ## Week 1 question ### Q1 ```clike= #include <stdio.h> #include <stdlib.h> #include <math.h> int main(){ char ID[10]; float Hcm; float W; float Hm; float BMI; printf("Enter ID: "); scanf("%s", ID); printf("Enter weight: "); scanf("%f", &W); printf("Enter height(cm): "); scanf("%f", &Hcm); Hm = Hcm / 100; BMI = W / pow(Hm,2); printf("%s Your BMI: %.1f", ID, BMI); } ``` ### Q2 ```clike= #include <stdio.h> #include <stdlib.h> int main(){ int n; int ans = 1; printf("Enter n: "); scanf("%d", &n); if (n == 0){ printf("0! is 1"); } else if (n < 0){ printf("number can't be less than 0"); }else{ int tmp = n; while (tmp > 0){ ans *= tmp; tmp--; } printf("%d! is %d", n, ans); } } ``` ### Q3: a006. 一元二次方程式 ```clike= #include <stdio.h> #include <stdlib.h> #include <math.h> int main(){ int a, b, c; int ans1, ans2; printf("請輸入a b c,中間使用空白區隔"); scanf("%d %d %d", &a, &b, &c); int num_in_sqrt = pow(b,2) - 4*a*c; if (num_in_sqrt < 0){ printf("No real root"); }else{ ans1 = (sqrt(num_in_sqrt) - b) / 2 * a; ans2 = (-sqrt(num_in_sqrt) - b) / 2 * a; if (ans1 == ans2){ printf("Two same roots x=%d", ans1); }else{ printf("Two different roots x1=%d , x2=%d", ans1, ans2); } } } ``` ### Q4: 10進位轉16進位 ```clike= #include <stdio.h> #include <stdlib.h> char buffer[33]; //用於存放轉換好的十六進位制字串,可根據需要定義長度 char* IntToHex(int aa) { sprintf(buffer, "%x", aa); return buffer; } int main () { int num; char* hex_str; printf ("Enter a number: "); scanf ("%d",&num); printf("%x", num); hex_str = IntToHex (num); printf ("Hexadecimal number: %sH\n", hex_str); return 0; } ``` ## Q5: Remove Duplicates from Sorted Array ### 題目敘述 input 會給你一個排序過後的陣列,實作一個 function 把重複的值剔除(in-place 移除,不分配額外的空間),使每個元素都只出現一次,function 回傳陣列的新長度。 ![](https://i.imgur.com/4hvgiQ7.png) ### 解法思路 用兩個index(i比較慢 & j比較快),如遇到重複的則i不會動,直到index j跳脫duplicate value的區域,如此確保index i所處理的資料均無重複 ```clike= int removeDuplicates(int* nums, int numsSize) { if (numsSize == 0) return 0; int i = 0; for (int j = 1; j < numsSize; j++) { if (nums[j] != nums[i]) { i++; nums[i] = nums[j]; } } return i + 1; } ``` ## Week 2 question ### Q1 略 ### Q2 Leetcode - Search Insert Position 法1: 暴力法 ```clike= #include <stdio.h> #include <stdlib.h> int searchInsert(int* nums, int numsSize, int target) { int i; for(i=0;i<numsSize;i++) { if(nums[i]>=target) return i; } return i; } int main () { int nums[] = {1,3,5,6}; int numsSize = sizeof(nums) / sizeof(int); int target; printf("Enter a num: "); scanf("%d", &target); int result = searchInsert(nums, numsSize, target); printf("Inserted index is %d", result); } ``` 法2: 二分法 ```clike= #include <stdio.h> #include <stdlib.h> int searchInsert(int* nums, int numsSize, int target) { int left = 0, right = numsSize - 1, mid = 0; while(left <= right) { mid = (left + right) / 2; if(nums[mid] == target) return mid; else if(nums[mid] > target) { right = mid - 1; } else left = mid + 1; } return left; } int main () { int nums[] = {1,3,5,6}; int numsSize = sizeof(nums) / sizeof(int); int target; printf("Enter a num: "); scanf("%d", &target); int result = searchInsert(nums, numsSize, target); printf("Inserted index is %d", result); } ``` ### Q3 Leetcode - Roman to Integer #### 思路: 使用一個map來儲存羅馬符號跟數字之間的對應關係,在一般的情況下(ex. III, VI),可以直接將羅馬符號轉換成數字。 不過如果出現IV,XC這種組合,就要另外處理,這種組合的特色是後面的符號會大於前面的符號,因此一次讀兩個羅馬符號來找出這種組合。 一次讀兩個羅馬數字,如果第二個數字(b)比第一個(a)大,b-a,b <= a,b+a。 ```clike= #include<stdio.h> #include<string.h> int toNumber(char ch) { switch (ch) { case 'I': return 1; case 'V': return 5; case 'X': return 10; case 'L': return 50; case 'C': return 100; case 'D': return 500; case 'M': return 1000; default: return -1; } } int romanToInt(char* s) { int total = 0; int i = 0; int a = 0; int b = 0; while(s[i] != '\0') { a=toNumber(s[i]); b=toNumber(s[i+1]); if(a >= b) { total += a; i++; } else { total = total + b - a; i += 2; } } return total; } int main(){ char roman_Number[1000]; printf("Enter any roman number (Valid digits are I, V, X, L, C, D, M): \n"); scanf("%s",roman_Number); int sum = romanToInt(roman_Number); if (sum != -1) printf("Its decimal value is : %d",sum); else printf("Wrong input"); return 0; } ``` ### Q4 Leetcode - Excel Sheet Column Number #### 思路 因為A的ASC II碼是65,那麼A-64=1。因此ABCD...等價於1,2,3,4...,Z等價於26,滿26進1。 接下來就是分別計算各個字母再相加就行了 ```clike= #include<stdio.h> #include<string.h> int titleToNumber(char* s){ int len = strlen(s); int output = 0; for(int i = 0; i < len; i++) { int temp = *(s+i) - 64; //臨時變量存放當前位上的值 *(s+i) = s[i] for(int j = 0; j < len-i-1; j++) { temp *= 26; //當前位的值乘上此位的權重,即乘以26的乘方 } output += temp; //把計算的權重值逐位相加 } return output; } int main(){ char title[1000]; printf("Enter column title:\n"); scanf("%s",title); int sum = titleToNumber(title); printf("Its decimal value is : %d",sum); return 0; } ``` ## HW1 題目: https://acm.cs.nthu.edu.tw/problem/12187/ 解答: ```clike= #include <stdio.h> #include <stdlib.h> // for atoi #include <string.h> #include <stdbool.h> #include <limits.h> int main(void) { int total_instruction_num; scanf("%d", &total_instruction_num); getchar(); // 吃掉換行字符 bool isFirst = true; int ans = 0; int total_num = 0; for (int i = 0; i < total_instruction_num; i++){ char s[50]; fgets(s, sizeof(s), stdin); // scanf碰到字串有空格會直接斷掉 // gets(s); // 不安全的function,以fgets代替 char *sub_str = strtok(s, " "); // 依照空白做切割 if (strcmp(sub_str, "sum") == 0){ sub_str = strtok(NULL, " "); // 把它想成取下一組就好 while (sub_str != NULL) { if (isFirst){ isFirst = false; total_num += atoi(sub_str); // atoi = alphbet to integer } else{ int num = atoi(sub_str); ans += num; } sub_str = strtok(NULL, " "); } } else if (strcmp(sub_str, "min") == 0){ sub_str = strtok(NULL, " "); int min = INT_MAX; while (sub_str != NULL) { int num = atoi(sub_str); if (num < min){ min = num; } sub_str = strtok(NULL, " "); } ans += min; total_num++; } else{ sub_str = strtok(NULL, " "); int max = INT_MIN; while (sub_str != NULL) { int num = atoi(sub_str); if (num > max){ max = num; } sub_str = strtok(NULL, " "); } ans += max; total_num++; } isFirst = true; } printf("%d %d", ans, total_num); return 0; } ``` ## HW2 題目: 讀檔,兩個字串相乘 解法: ```clike= #include <stdio.h> // int charToint(char str){ // return (int)str - '0'; // } int main() { // region: 讀檔&生成矩陣 char InputFileName[] = "input.txt"; char OutputFileName[] = "../output.txt"; FILE *fp; FILE *out_fp; char StrLine[1024]; //每行最大讀取的字元數 int m,n,k; if((fp = fopen(InputFileName,"r")) == NULL) //判斷檔案是否存在及可讀 { printf("error!"); return -1; } fscanf(fp, "%d %d %d", &m, &n, &k); int a[m][n],b[n][k],ans[m][k]; while (!feof(fp)) { printf("---preprocess---\n"); for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { fscanf(fp, "%d", &a[i][j]); printf("%d ", a[i][j]); } printf("a\n"); } for(int i=0;i<n;i++) { for(int j=0;j<k;j++) { fscanf(fp, "%d", &b[i][j]); printf("%d ", b[i][j]); } printf("b\n"); } printf("---preprocess done---\n"); if((out_fp = fopen(OutputFileName,"w")) == NULL) //判斷檔案是否存在及可讀 { printf("error!"); return -1; } for(int i=0;i<m;i++) { for(int j=0;j<k;j++){ ans[i][j] = 0; for(int q=0;q<n;q++){ ans[i][j] += a[i][q] * b[q][j]; } fprintf(out_fp, "%d ", ans[i][j]); } fprintf(out_fp, "\n"); } /// region: 因為有負數,所以不能這樣preprocess // for(int i=0;i<m;i++) // { // fgets(StrLine,1024,fp); //讀取一行 // for(int j=0;j<n;j++) // { // a[i][j] = charToint(StrLine[2*j]); // printf("%d ", a[i][j]); // } // printf("\n"); // } // for(int i=0;i<n;i++) // { // fgets(StrLine,1024,fp); //讀取一行 // for(int j=0;j<k;j++) // { // b[i][j] = charToint(StrLine[2*j]); // printf("%d ", b[i][j]); // } // printf("\n"); // } /// } fclose(fp); //關閉檔案 // endregion return 0; } ``` ## 題庫 a022: 迴文 ```clike= #include <stdio.h> #include <stdlib.h> #include <string.h> char* get_reverse(char* src){ int n = strlen(src); char* src_reverse = malloc(n); for (int i = 0; i < n; i++){ src_reverse[n-i-1] = src[i]; } return src_reverse; } int main(){ char src[1000]; while (scanf("%s", src) != EOF){ char* src_reversed = get_reverse(src); if (strcmp(src, src_reversed) == 0){ printf("yes\n"); }else{ printf("no\n"); } } } ``` a015: 矩陣的翻轉 ```clike= #include <stdio.h> #include <stdlib.h> int main(){ int row; int col; while (scanf("%d %d", &row, &col) != EOF){ int input_matrix[row][col]; int output_matrix[col][row]; for (int i = 0; i < row; i++){ for (int j = 0; j < col; j++){ scanf("%d", &input_matrix[i][j]); output_matrix[j][i] = input_matrix[i][j]; } } for (int i = 0; i < col; i++){ for (int j = 0; j < row; j++){ printf("%d ", output_matrix[i][j]); } printf("\n"); } } } ``` ## 補充 讀取任意輸入數量的數字 https://www.itread01.com/content/1546317753. # 期中考 Q1: oj 12216 ```clike= #include <stdio.h> #include <stdlib.h> int main() { int m,n,k; int s=1; scanf("%d %d %d",&m,&n,&k); //從INPUT 讀第一行 int a[m][n]; int b[n][k]; int ans[m][k]; // *** here *** for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { scanf("%d", &a[i][j]); } } for(int i=0;i<n;i++) { for(int j=0;j<k;j++) { scanf("%d", &b[i][j]); } } // *** here *** for(int i=0;i<m;i++) { //計算a*b矩陣=ans for(int j=0;j<k;j++) { ans[i][j]=0; for(int q=0;q<n;q++) { ans[i][j] += a[i][q]*b[q][j]; } } } for(int i=0;i<m;i++) { //寫出a*b矩陣 for(int j=0;j<k;j++) { if(s==1) { printf("%d",ans[i][j]); s=0; } else if(s==0) { // *** here *** printf(" %d",ans[i][j]); } } s=1; if(i<m-1) { printf("\n"); } } } ``` # 作業 postfix calculation ```clike= #include <stdio.h> int stack[100]; int top=-1; void push(int x){ top = top + 1; stack[top]=x; } int pop(){ int res; res=stack[top--]; return res; } int main(){ char eq[100]; int i=0,num,n1,n2,n3; scanf("%s",eq); while(eq[i]!=NULL) { if(isdigit(eq[i])) { num=eq[i]-48; push(num); } else { n1=pop(); n2=pop(); switch(eq[i]) { case'+': n3=n1+n2; push(n3); break; case'-': n3=n2-n1; push(n3); break; case'*': n3=n1*n2; push(n3); break; case'/': n3=n2/n1; push(n3); break; } } i++; } printf("%d",n3); return 0; } ``` infix calculation ```clike= #include <stdio.h> #include <ctype.h> int stack[100]; int top=-1; void push(int x){ top = top + 1; stack[top]=x; } int pop(){ int res; res=stack[top--]; return res; } int priority(char op) { switch(op) { case '+': case '-': return 1; case '*': case '/': return 2; default: return 0; } } void inToPostfix(char* infix, char* postfix) { char local_stack[80] = {'\0'}; int i, j, local_top; for(i = 0, j = 0, local_top = 0; infix[i] != '\0'; i++){ switch(infix[i]) { case '(': // 運算子堆疊 local_stack[++local_top] = infix[i]; break; case '+': case '-': case '*': case '/': while(priority(local_stack[local_top]) >= priority(infix[i])) { postfix[j++] = local_stack[local_top--]; } local_stack[++local_top] = infix[i]; // 存入堆疊 break; case ')': while(local_stack[local_top] != '(') { // 遇 ) 輸出至 ( postfix[j++] = local_stack[local_top--]; } local_top--; // 不輸出 ( break; default: // 運算元直接輸出 postfix[j++] = infix[i]; } } while(local_top > 0) { postfix[j++] = local_stack[local_top--]; } } int main(){ char infix[80] = {'\0'}; char postfix[80]= {'\0'}; // printf("中序運算式:"); scanf("%s", infix); inToPostfix(infix, postfix); // printf("%s", postfix); // char postfix[100]; int i=0,num,n1,n2,n3; while(postfix[i]!='\0') { if(isdigit(postfix[i])) { num=postfix[i]-48; push(num); } else { n1=pop(); n2=pop(); switch(postfix[i]) { case'+': n3=n1+n2; push(n3); break; case'-': n3=n2-n1; push(n3); break; case'*': n3=n1*n2; push(n3); break; case'/': n3=n2/n1; push(n3); break; } } i++; } printf("%d",n3); return 0; } ``` Week15 ```clike= #include <stdio.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> #define M 6 #define N 6 typedef struct node_t { int x, y; int dir; }node; #define MAXSIZE 100 /*定義最大堆疊容量*/ node s[MAXSIZE]; //堆疊的陣列宣告 int top=-1; //堆疊的頂端 int isempty() { if(top == -1) return 1; else return 0; } int isfull() { if(top == MAXSIZE) return 1; else return 0; } node peek() { return s[top]; } node pop() { node data; if(!isempty()) { data = s[top]; top = top - 1; return data; } else { printf("Could not retrieve data, Stack is empty.\n"); } } void push(node data) { if(!isfull()) { top = top + 1; s[top] = data; } else { printf("Could not insert data, Stack is full.\n"); } } // Coordinates of food int fx, fy; bool unvisited[M][N]; bool isReachable(int maze[M][N]) { // Initially starting at (0, 0). int i = 0, j = 0; node temp = { i, j, 0 }; push(temp); while (!isempty()) { // Pop the top node and move to the // left, right, top, down or retract // back according the value of node's // dir variable. temp = peek(); int d = temp.dir; i = temp.x, j = temp.y; // Increment the direction and // push the node in the stack again. temp.dir++; pop(); push(temp); // If we reach the Food coordinates // return true if (i == fx && j == fy) { return true; } // Checking the Up direction. if (d == 0) { if (i - 1 >= 0 && maze[i - 1][j] && unvisited[i - 1][j]) { node temp1 = { i - 1, j, 0 }; unvisited[i - 1][j] = false; push(temp1); } } // Checking the left direction else if (d == 1) { if (j - 1 >= 0 && maze[i][j - 1] && unvisited[i][j - 1]) { node temp1 = {i, j - 1, 0 }; unvisited[i][j - 1] = false; push(temp1); } } // Checking the down direction else if (d == 2) { if (i + 1 < M && maze[i + 1][j] && unvisited[i + 1][j]) { node temp1 = {i + 1, j, 0 }; unvisited[i + 1][j] = false; push(temp1); } } // Checking the right direction else if (d == 3) { if (j + 1 < N && maze[i][j + 1] && unvisited[i][j + 1]) { node temp1 = {i, j + 1, 0 }; unvisited[i][j + 1] = false; push(temp1); } } // If none of the direction can take // the rat to the Food, retract back // to the path where the rat came from. else { unvisited[temp.x][temp.y] = true; pop(); } } // If the stack is empty and // no path is found return false. return false; } // Driver code int main() { // Initially setting the unvisited // true = unvisited memset(unvisited, true, sizeof(unvisited)); char InputFileName[] = "input.txt"; FILE *fp; char StrLine[1024]; //每行最大讀取的字元數 if((fp = fopen(InputFileName,"r")) == NULL) //判斷檔案是否存在及可讀 { printf("error!"); return -1; } // Maze matrix int maze[M][N] = {0}; for(int i=0;i<M;i++) { for(int j=0;j<N;j++) { fscanf(fp, "%d", &maze[i][j]); } } fscanf(fp, "%d %d", &fx, &fy); if (isReachable(maze)) printf("Yes\n"); else printf("No\n"); for (int i = 0; i <= top; i++){ printf("(%d %d) ", s[i].x, s[i].y); } return 0; } ``` ## final 更改成可重複遊玩版本 ```clike= #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 10 int chessboard[N + 1][N + 1] = { 0 }; int whoseTurn = 0; void initGame(); void printChessboard(); int playChess(); int judge(int, int); void play(){ initGame(); while (1) { ++whoseTurn; int isEnd = playChess(); if (isEnd != 0) break; } } int main() { while (1){ play(); getchar(); printf("Continue? y or n"); char again; scanf("%c", &again); if (again != 'y'){ printf("%c", again); break; } } return 0; } void initGame(void) { whoseTurn = 0; memset(chessboard, 0, sizeof(chessboard)); system("cls"); printChessboard(); } void printChessboard() { int i, j; for (i = 0; i <= N; i++) { for (j = 0; j <= N; j++) { if (0 == i) printf("%3d", j); else if (j == 0) printf("%3d", i); else if (1 == chessboard[i][j]) printf(" O"); else if (2 == chessboard[i][j]) printf(" X"); else printf(" *"); } printf("\n"); } } int playChess(void) { int i, j; if (1 == (whoseTurn & 1)) { printf("Turn to player 1, please input the position:"); scanf("%d %d", &i, &j); while (chessboard[i][j] != 0) { printf("This position has been occupied, please input the position again:"); scanf("%d %d", &i, &j); } chessboard[i][j] = 1; } else { printf("Turn to player 2, please input the position:"); scanf("%d %d", &i, &j); while (chessboard[i][j] != 0) { printf("This position has been occupied, please input the position again:"); scanf("%d %d", &i, &j); } chessboard[i][j] = 2; } system("cls"); printChessboard(); if (judge(i, j)) { if (1 == (whoseTurn & 1)) { printf("Winner is player 1!\n"); return 1; } else { printf("Winner is player 2!\n"); return 2; } } return 0; } int judge(int x, int y) { int i, j; int t = 2 - (whoseTurn & 1); for (i = x - 4, j = y; i <= x; i++) { if (i >= 1 && i <= N && t == chessboard[i][j] && t == chessboard[i + 1][j] && t == chessboard[i + 2][j] && t == chessboard[i + 3][j] && t == chessboard[i + 4][j]) return 1; } for (i = x, j = y - 4; j <= y; j++) { if (j >= 1 && j <= N && t == chessboard[i][j] && t == chessboard[i][j + 1] && t == chessboard[i][j + 2] && t == chessboard[i][j + 3] && t == chessboard[i][j + 4]) return 1; } for (i = x - 4, j = y - 4; i <= x, j <= y; i++, j++) { if (i >= 1 && i <= N && j >= 1 && j <= N && t == chessboard[i][j] && t == chessboard[i + 1][j + 1] && t == chessboard[i + 2][j + 2] && t == chessboard[i + 3][j + 3] && t == chessboard[i + 4][j + 4]) return 1; } for (i = x + 4, j = y - 4; i >= 1, j <= y; i--, j++) { if (i >= 1 && i <= N && j >= 1 && j <= N && t == chessboard[i][j] && t == chessboard[i - 1][j + 1] && t == chessboard[i - 2][j + 2] && t == chessboard[i - 3][j + 3] && t == chessboard[i - 4][j + 4]) return 1; } return 0; } ```