# 家教解答
題目:
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 回傳陣列的新長度。

### 解法思路
用兩個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;
}
```