# 東華大學資管系初階程式設計(進階題)112年考古
## 相關資訊
課程代碼:IM__1120AA-初階程式設計
老師:劉英和教授
使用程式:C++
[初階考古](https://hackmd.io/@sumo0711/SyFipiOfA)
## 免責申明
:::danger
此文件僅為個人參考解答,並非標準答案。請僅供個人學習使用,切勿用於商業用途,如有侵權請寫信告知。
:::
## 生活費
### Description
小鳴剛上大學拿到人生第一份零用錢,他希望寫一支可以幫他計算每天預算的程式。
請你讓小鳴可以輸入他的生活費,
幫他除以剩餘的天數,算出他每天可以用多少(如果有小數則無條件捨棄)。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請問您有多少生活費:**10000**
還剩下幾天需要過:**30**
您一天可以使用333元
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
int pocket_money, day; // 利用 int 型態無條件捨去小數點後面的數字
cout << "請問您有多少生活費:";
cin >> pocket_money;
cout << "還剩下幾天需要過:";
cin >> day;
pocket_money = pocket_money / day;
cout << "您一天可以使用" << pocket_money << "元";
return 0;
}
```
## 時分秒
### Description
「再等我15分鐘!」小依邊化著妝說著。
「每次等妳出門都好久」小鳴無奈。
「那等我900秒好了。」小鈴改口。
「ok!」小鳴覺得秒比分快多了,立刻答應。
仔細思考後,他就開始後悔了。
小鳴每次都無法快速轉換秒數和小時、分、秒,請你寫一個程式幫他吧!
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請輸入您要轉換的秒數:**4853**
轉換結果為:
1小時20分鐘53秒
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
int s, m, h, number;
cout << "請輸入你想轉換的秒數:";
cin >> number;
h = number / 3600; // 一小時為3600秒
number = number % 3600; // 將餘數帶回 number
m = number / 60; // 一分鐘為60秒
s = number % 60; // 餘數為秒
cout << "轉換結果為:\n" << h << "小時" << m << "分鐘" << s << "秒";
return 0;
}
```
## 轉換電腦進位
### Description
請編寫一個程式,接受使用者輸入一個十進位數字,然後將該數字轉換為二進位、八進位和十六進位的表示形式,並輸出結果。
提示:
可以使用適當的內建函數或自行編寫轉換函數來實現進制轉換。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請輸入一個十進位數字:**42**
轉換結果:
二進位表示:101010
八進位表示:52
十六進位表示:2A
### Solution
```ccp=
#include <iostream>
#include <bitset> //bitset
#include <iomanip> //setiosflags(ios::uppercase)
using namespace std;
int main()
{
int ten_number;
cout << "請輸入一個十進位的數字:";
cin >> ten_number;
cout << "轉換結果:\n";
bitset<100> b(ten_number); // 把10進位ten_number放到bitset進行轉換
string s = b.to_string(); // 轉換成string
s.erase(0, s.find_first_not_of('0')); // 利用string函數去除前面的0
cout << "二進位表示:" << s << endl;
// bitset<6> b(ten_number);
// cout << "二進位表示:" << b << endl; // 原本寫的
cout << oct << "八進位表示:" << ten_number << endl;
cout << setiosflags(ios::uppercase) << hex << "十六進位表示:" << ten_number; // setiosflags(ios::uppercase)將十六進位abc轉換成大寫ABC
return 0;
}
```
## 字串
### Description
請使用四種不同的方法的其中一種來實現以下多行字串:
```
Hello, World!
This is a multiline string.
It contains:
- Bulleted
- Nested
- Items
- And some code:
int x = 10;
int y = 20; int sum = x + y;
```
(四種方法分別為String Literals、Backslash Character和
Raw String Literals)
#### String Literals
\n = 換行
\t = tab
#### Backslash Character
\ = 接續上一行程式
#### Raw String Literals
R"(能打任何字排版字串)"
### Example
```
Hello, World!
This is a multiline string.
It contains:
- Bulleted
- Nested
- Items
- And some code:
int x = 10;
int y = 20; int sum = x + y;
```
### Solution
```cpp=
#include <iostream>
#include <string>
using namespace std;
int main()
{
cout << "Hello, World!\n\
This is a multiline string.\n\
It contains:\n\
\t- Bulleted\n\
\t\t- Nested\n\
\t\t\t- Items\n\
\t- And some code:\n\
\t\tint x = 10;\n\
\t\tint y = 20; int sum = x + y;";
return 0;
}
```
## 一元二次方程式
### Description
寫一個幫忙解一元二次方程式的程式
(輸出的數字只到小數點第二位,且希望輸入一元二次方程式的a,b和c係數時,僅用空格隔開。)
(使用三元運算符)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請輸入一元二次方程式的係數a,b,c:**1 5 6**
方程式有兩個實根:-2.00 & -3.00
### Solution
```cpp=
#include <iostream>
#include <iomanip>
#include <cmath> // 數學函式庫
using namespace std;
// 一般二元一次方程式: ax^2 + bx + c = 0
// 判别式的計算方式是: Δ = b^2 - 4ac
// 其中,Δ表示判别式(discriminant),b是x的一次系數,a是x的二次系數,c是常數。
// 如果 Δ > 0,有兩個不相等的實根。
// 如果 Δ = 0,有兩個相等的實根。
// 如果 Δ < 0,沒有實根。
// 求解的公式 x = (-b ± √Δ) / (2a)
int main()
{
double a, b, c, root1, root2, root3;
cout << "請輸入一元二次方程式的係數a,b,c:";
cin >> a >> b >> c;
double discriminant = b * b - 4 * a * c;
int roots = (discriminant > 0) ? 2 : (discriminant == 0) ? 1 : 0;
// discriminant = b^2 - 4ac
// discriminant>0 roots=2 , discriminant=0 roots=1 , discriminant<0 roots=0
cout << "方程式";
switch (roots)
{
case 2: // roots=2
root1 = (-b + sqrt(discriminant)) / (2 * a); // x = (-b + √Δ) / (2a)
root2 = (-b - sqrt(discriminant)) / (2 * a); // x = (-b - √Δ) / (2a)
cout << "有兩個實根: " << fixed << setprecision(2) << root1 << " & " << root2;
break;
case 1: // roots=1
root3 = -b / (2 * a);
cout << "有一個實根: " << fixed << setprecision(2) << root3;
break;
default: // roots=0
cout << "無實根";
break;
}
}
```
### Verify
請輸入一元二次方程式的係數a,b,c:**1 -6 9**
方程式有一個實根: 3.00
請輸入一元二次方程式的係數a,b,c:**1 2 3**
方程式無實根
## 三元運算符
### Description
寫一個可以判斷輸入的三個數字是否可以組成一個三角形
(使用三元運算符)
#### 三元運算符
if else 的另一種寫法
>(判斷式)?成立要做的事:否則做這個
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請輸入三個正整數: **3 4 5**
這三個數能組成一個三角形。
### Solution
```cpp=
#include <iostream>
using namespace std;
// 三角形不等式(Triangle Inequality)任意兩邊的總長度必須大於或等於第三邊的長度。
// 具體來說,對於一個三角形,假設三邊的長度分別為 a、b 和 c,則三角形不等式可以表達如下:
// a + b > c
// a + c > b
// b + c > a
// 如果這些不等式都成立,則這三個邊可以形成一個有效的三角形。
// 如果有任何一個不等式不成立,則無法構成三角形。
int main()
{
int a, b, c;
cout << "請輸入三個正整數: ";
cin >> a >> b >> c;
cout << ((a + b > c) && (a + c > b) && (b + c > a) ? "這三個數能組成一個三角形。" : "這三個數無法組成一個三角形。");
}
```
### Verify
請輸入三個正整數: **1 2 4**
這三個數無法能組成一個三角形。
## Try-Catch
### Description
請設計一個程式, 可以幫忙處理克拉瑪法則的計算,克拉瑪法則是一種用於解線性方程的方法。
(需包含try catch來保護程式碼)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
請輸入第一個方程式的係數(a1,b1,c1): **2 3 2**
請輸入第二個方程式的係數(a2,b2,c2): **3 4 2**
x的值為: -2
y的值為: 2
### Solution
```cpp=
#include <iostream>
#include <stdexcept> // Try-catch
using namespace std;
// 克拉瑪公式
// 方程式一:a1X + b1Y = c1
// 方程式二:a2X + b2Y = c2
// Delta = (a1 * b2) - (a2 * b1)
// X = (c1 * b2) - (c2 * b1) / Delta
// Y = (c1 * a2) - (c2 * a1) / (a2 * b1) - (a1 * b2)
// 條件一:若 Delta 不等於 0,則方程有一組解 X Y
// 條件二:若 Delta = 0,但 X Y 至少有一個不為 0,方程式無解
// 條件三:若 Delta = X = Y = 0,方程式無限多解
int main()
{
try
{
double a1, a2, b1, b2, c1, c2, x, y;
cout << "請輸入第一個方程式的係數(a1,b1,c1): ";
if (!(cin >> a1) || !(cin >> b1) || !(cin >> c1)) // 判斷使用者輸入是否為整數
throw runtime_error("請輸入整數");
cout << "請輸入第二個方程式的係數(a2,b2,c2): ";
if (!(cin >> a2) || !(cin >> b2) || !(cin >> c2)) // 判斷使用者輸入是否為整數
throw runtime_error("請輸入整數");
x = (c1 * b2 - c2 * b1) / (a1 * b2 - a2 * b1);
y = (c1 * a2 - c2 * a1) / (a2 * b1 - a1 * b2);
if ((a1 * b2 - a2 * b1) == 0) // 判斷 Delta 是否為 0
{
if ((x < 0) || (x > 0) || (y < 0) || (y > 0)) // 判斷 X Y 至少有一個不為 0
throw runtime_error("方程式無解");
else
throw runtime_error("方程式無限多組解"); // X = Y = 0
}
// 無錯誤印出 X Y 的值
cout << "x的值為: " << x << endl
<< "y的值為: " << y << endl;
}
catch (const runtime_error &e) // e 為 runtime_error 的變數
{
cout << "錯誤: " << e.what() << endl; // 輸出錯誤訊息
}
return 0;
}
```
### Verify
請輸入第一個方程式的係數(a1,b1,c1): **q 1 3**
錯誤: 請輸入整數
請輸入第一個方程式的係數(a1,b1,c1): **6 4 -18**
請輸入第二個方程式的係數(a2,b2,c2): **3 2 -1**
錯誤: 方程式無解
請輸入第一個方程式的係數(a1,b1,c1): **0 0 0**
請輸入第二個方程式的係數(a2,b2,c2): **0 0 0**
錯誤: 方程式無限多組解
## 猜數字
### Description
電腦以亂數產生一小於100的正整數(num),使用者不斷猜測該數(guess),每次猜測時電腦會提示猜的太大或太小,直到猜到或者猜超過五次為止。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Your guess?
**50**
Too high!
Guess again!(remaining times: 5)
**25**
Too high!
Guess again!(remaining times: 4)
**12**
Too low!
Guess again!(remaining times: 3)
**18**
Too high!
Guess again!(remaining times: 2)
**15**
Too low!
Guess again!(remaining times: 1)
**17**
Too high!
Game over!
### Solution
```cpp=
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int main()
{
int num, Answer, guess_num = 6;
srand(time(NULL)); // 取得時間序列
Answer = rand() % 100 + 1; // 取亂數 1-100
// rand() 生成一個隨機整數。
// %100 確保結果在0到99的範圍內。
// +1 然後將範圍移動到1到100。
cout << "Your guess?\n";
while (guess_num > 0) // 6 次猜數字的機會
{
cin >> num;
if (num == Answer)
{
cout << "Bingo!";
break; // 直到使用者猜到答案 跳出 while
}
else
cout << ((num > Answer) ? "Too high!\n" : "Too low!\n");
// 如果使用者輸入大於 Answer 輸出 Too high! 否則輸出 Too low!
guess_num -= 1;
if (guess_num == 0)
continue; // 如果 guess_num = 0 跳過這次迴圈
cout << "Guess again!(remaining times: " << guess_num << ")\n";
}
if (guess_num == 0) // 如果猜滿五次還沒猜出
cout << "Game over!\n";
return 0;
}
```
## 消失的等差數列
### Description
你穿越成為一名天才偵探,遇到一個極具挑戰性的任務。在古老的地圖上,標記了兩串有規律的數字(等差級數),代表寶藏的座標。這兩串數字是經過精心安排的,但其中有兩個數字(以*來表示)被小偷偷走,使得你無法直接找到寶藏的位置。然而,你聰明的頭腦讓你想到可以設計一個程式,透過找出這兩個缺失的數字,來找到小偷藏寶藏的位置。給定兩串整數陣列A和B,假設它們都有相同的長度N,且內容都是1到N的整數,代表寶藏的座標。請你設計一個程式,找出在陣列A和陣列B中缺失的兩個數字。這兩個缺失的數字就是小偷所偷走的座標,將它們輸出後,你將能找到寶藏的位置,並成功解開這個謎題。
〈提示:用等差級數的公式解〉
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please enter the array length:
N=**10**
1 6 11 16 21 26 31 36 * 46
1 9 17 25 33 41 49 57 65 *
A[] common difference = 5
B[] common difference = 8
The disappearing array is:
A[8]=41 B[9]=73
### Solution
```cpp=
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
int N, D_A, D_B; // 數列長度 AB數列公差
void Random(int &RemoveA_par, int &RemoveB_par, int &D_A_par, int &D_B_par);
// 隨機取得要刪除陣列的數字 與 AB公差的值
void Initialize(int Initialize_A_par[], int Initialize_B_par[]);
// 初始化AB陣列
void Sum_before(int &Total_A_Sum_par, int &Total_B_Sum_par);
// 計算陣列和
int Sum_after(int Sum_par[]);
// 把刪除陣列後的數值加起來
int main()
{
cout << "Please enter the array length:\nN=";
cin >> N; // 輸入陣列長度
int A[N], B[N], RemoveA, RemoveB, MissA, MissB, Total_A_Sum, Total_B_Sum;
Random(RemoveA, RemoveB, D_A, D_B); // 取得要刪除的陣列數字 與 AB公差的值
Initialize(A, B); // 初始化陣列
Sum_before(Total_A_Sum, Total_B_Sum); // 等差級數公式解
A[RemoveA] = 0; // 刪除陣列的值
B[RemoveB] = 0;
MissA = Total_A_Sum - Sum_after(A); // 將原本的總和 - 刪除後的陣列總和 = 少掉的數字
MissB = Total_B_Sum - Sum_after(B);
cout << "A[] common difference = " << D_A << endl // 印出公差
<< "B[] common difference = " << D_B << endl;
cout << "The disappearing array is:\nA[" << RemoveA << "]=" << MissA << "\tB[" << RemoveB << "]=" << MissB;
return 0;
}
void Random(int &RemoveA_par, int &RemoveB_par, int &D_A_par, int &D_B_par)
{
srand(time(NULL)); // 取得時間序列
RemoveA_par = rand() % N; // 取得陣列要刪除的數字
RemoveB_par = rand() % N;
D_A_par = rand() % 10 + 1; // 取得陣列差的數字 取 1-10
D_B_par = rand() % 10 + 1;
}
void Initialize(int Initialize_A_par[], int Initialize_B_par[])
{
// G 為暫存值的變數 每增加一圈用複利的觀念
for (int i = 0, G = 0; i < N; i++, G += D_A) // 賦予陣列數值
Initialize_A_par[i] = G + 1; // 從 1 開始賦予
for (int i = 0, G = 0; i < N; i++, G += D_B)
Initialize_B_par[i] = G + 1;
}
void Sum_before(int &Total_A_Sum_par, int &Total_B_Sum_par)
{
Total_A_Sum_par = N * (2 + (N - 1) * D_A) / 2; // 等差級數公式解
Total_B_Sum_par = N * (2 + (N - 1) * D_B) / 2;
}
int Sum_after(int Sum_par[])
{
int sum = 0;
for (int i = 0; i < N; i++)
{
if (Sum_par[i] == 0) // 如果碰到被移除的數字 就印出 * 顯示
cout << '*' << " ";
else
cout << Sum_par[i] << " ";
sum += Sum_par[i]; // 把所有陣列數值相加
}
cout << endl;
return sum;
}
```
## 計算機
### Description
請設計一個簡易的計算機程式,該程式能夠讓使用者選擇四種基本的算術運算:加法、減法、乘法和除法。程式將要求使用者輸入兩個整數數字,然後根據使用者選擇的運算符號執行相應的計算。如果選擇的是除法,並且第二個數字為零,則程式會輸出「Cannot divide by zero!」的錯誤訊息。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Select +, -, * and / :
**+**
Enter two integers:
**2**
**4**
6
### Solution
```cpp=
#include <iostream>
using namespace std;
void Input(int &num1, int &num2);
int main()
{
try
{
int num1, num2;
char choose;
cout << "Select +, -, * and / :\n";
cin >> choose;
if (choose == '+')
{
Input(num1, num2);
cout << num1 + num2;
}
else if (choose == '-')
{
Input(num1, num2);
cout << num1 - num2;
}
else if (choose == '*')
{
Input(num1, num2);
cout << num1 * num2;
}
else if (choose == '/')
{
Input(num1, num2);
if (num2 == 0)
throw runtime_error("Cannot divide by zero!");
cout << num1 / num2;
}
else
throw runtime_error("Undefined Input");
}
catch (const runtime_error &e) // e 為 runtime_error 的變數
{
cout << "Error: " << e.what() << endl; // 輸出錯誤訊息
}
return 0;
}
void Input(int &num1, int &num2)
{
cout << "Enter two integers:\n";
cin >> num1 >> num2;
}
```
### Verify
Select +, -, * and / :
**/**
Enter two integers:
**9**
**0**
Error: Cannot divide by zero!
Select +, -, * and / :
**a**
Error: Undefined Input
## 質數
### Description
設計一個程式,讓使用者輸入一個正整數,列出所有小於它的質數並相加,輸出於螢幕。
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please enter a positive integer:
**20**
The prime number is:
2 3 5 7 11 13 17 19
The sum is: 77
### Solution
```cpp=
#include <iostream>
using namespace std;
int main()
{
int prime, num, sum = 0;
cout << "Please enter a positive integer:\n";
cin >> num;
cout << "The prime number is:\n";
for (int i = 2; i <= num; i++)
{
prime = 1; // 讓prime在 j 迴圈完之後又回到1
for (int j = 2; j <= (i / 2); j++)
{
if (i % j == 0)
prime = 0;
}
if (prime == 1)
{
cout << i << " ";
sum += i;
}
}
cout << endl << "The sum is: " << sum;
return 0;
}
```
## 費氏數列
### Description
fib 費式數列
(請用RecursiveFunction撰寫)
### Example
參考執行畫面如下:(粗體字為使用者輸入的)
Please enter the Fibonacci sequence to be calculated:
**10**
The value of Fibonacci sequence is:
55
### Solution
```cpp=
#include <iostream>
using namespace std;
// 費氏數列
// 公式 F(0)=0, F(1)=1, F(n)=F(n−1)+F(n−2)
int fib(int n);
int main()
{
int n;
cout << "Please enter the Fibonacci sequence to be calculated:\n";
cin >> n;
cout << "The value of Fibonacci sequence is:\n" << fib(n);
return 0;
}
int fib(int n)
{
return (n == 0 || n == 1) ? n : (fib(n - 1) + fib(n - 2));
// n 為 0 或 1 時,直接返回 n,作為遞迴的終止條件。
}
```
## 排列組合
### Description
勇敢的冒險家在神秘森林尋找魔法寶藏。魔法石上有五個字母:“a”、“b”、“c”、“d”和“e"。解開所有字母的全部排列,就能啟動魔法力量。請你撰寫一支程式幫助冒險家。
(請用Recursive Function撰寫)
### Example
a b c d e
a b c e d
a b d c e
a b d e c
a b e d c
a b e c d
a c b d e
a c b e d
a c d b e
a c d e b
a c e d b
a c e b d
a d c b e
a d c e b
a d b c e
a d b e c
a d e b c
a d e c b
a e c d b
a e c b d
a e d c b
a e d b c
a e b d c
a e b c d
b a c d e
b a c e d
b a d c e
b a d e c
b a e d c
b a e c d
b c a d e
b c a e d
b c d a e
b c d e a
b c e d a
b c e a d
b d c a e
b d c e a
b d a c e
b d a e c
b d e a c
b d e c a
b e c d a
b e c a d
b e d c a
b e d a c
b e a d c
b e a c d
c b a d e
c b a e d
c b d a e
c b d e a
c b e d a
c b e a d
c a b d e
c a b e d
c a d b e
c a d e b
c a e d b
c a e b d
c d a b e
c d a e b
c d b a e
c d b e a
c d e b a
c d e a b
c e a d b
c e a b d
c e d a b
c e d b a
c e b d a
c e b a d
d b c a e
d b c e a
d b a c e
d b a e c
d b e a c
d b e c a
d c b a e
d c b e a
d c a b e
d c a e b
d c e a b
d c e b a
d a c b e
d a c e b
d a b c e
d a b e c
d a e b c
d a e c b
d e c a b
d e c b a
d e a c b
d e a b c
d e b a c
d e b c a
e b c d a
e b c a d
e b d c a
e b d a c
e b a d c
e b a c d
e c b d a
e c b a d
e c d b a
e c d a b
e c a d b
e c a b d
e d c b a
e d c a b
e d b c a
e d b a c
e d a b c
e d a c b
e a c d b
e a c b d
e a d c b
e a d b c
e a b d c
e a b c d
### Solution
```cpp=
#include <iostream>
using namespace std;
void swap(char &a, char &b);
void undo(char arr[], int start, int end);
int main()
{
char abcde[5] = {'a', 'b', 'c', 'd', 'e'};
undo(abcde, 0, 4);
return 0;
}
// 交換兩個字
void swap(char &a, char &b)
{
char temp = a;
a = b;
b = temp;
}
void undo(char arr[], int start, int end)
{
// 如果已經處理到最後一個元素,輸出排列
if (start == end)
{
for (int i = 0; i <= end; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
else
{
// 初始 start=0 end=4 逐一進行交換
for (int i = start; i <= end; i++)
{
// 交換位置
swap(arr[start], arr[i]);
// 遞迴處理下一層
undo(arr, start + 1, end);
// 恢復原始順序,準備下一次交換
swap(arr[start], arr[i]);
}
}
}
```