Skip to content

训练营基础阶段作业 #18

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion exercises/00_hello_world/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@

int main(int argc, char **argv) {
// TODO: 在控制台输出 "Hello, InfiniTensor!" 并换行
std::cout : "Hello, InfiniTensor!" + std::endl;
std::cout << "Hello, InfiniTensor!" << std::endl;
return 0;
}
2 changes: 1 addition & 1 deletion exercises/01_variable&add/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

int main(int argc, char **argv) {
// TODO: 补全变量定义并打印加法运算
// x ?
int x = 1;// x ?
std::cout << x << " + " << x << " = " << x + x << std::endl;
return 0;
}
4 changes: 3 additions & 1 deletion exercises/02_function/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// NOTICE: 补充由内而外读法的机翻解释 <https://learn.microsoft.com/zh-cn/cpp/c-language/interpreting-more-complex-declarators?view=msvc-170>

// TODO: 在这里声明函数
int add(int a, int b);

int main(int argc, char **argv) {
ASSERT(add(123, 456) == 123 + 456, "add(123, 456) should be 123 + 456");
Expand All @@ -16,4 +17,5 @@ int main(int argc, char **argv) {

int add(int a, int b) {
// TODO: 补全函数定义,但不要移动代码行
}
return a + b;
}
10 changes: 5 additions & 5 deletions exercises/03_argument&parameter/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@ void func(int);
// TODO: 为下列 ASSERT 填写正确的值
int main(int argc, char **argv) {
auto arg = 99;
ASSERT(arg == ?, "arg should be ?");
ASSERT(arg == 99, "arg should be 99");
std::cout << "befor func call: " << arg << std::endl;
func(arg);
ASSERT(arg == ?, "arg should be ?");
ASSERT(arg == 99, "arg should be 99");
std::cout << "after func call: " << arg << std::endl;
return 0;
}

// TODO: 为下列 ASSERT 填写正确的值
void func(int param) {
ASSERT(param == ?, "param should be ?");
ASSERT(param == 99, "param should be 99");
std::cout << "befor add: " << param << std::endl;
param += 1;
ASSERT(param == ?, "param should be ?");
ASSERT(param == 100, "param should be 100");
std::cout << "after add: " << param << std::endl;
}
}
12 changes: 6 additions & 6 deletions exercises/04_static/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ static int func(int param) {

int main(int argc, char **argv) {
// TODO: 将下列 `?` 替换为正确的数字
ASSERT(func(5) == ?, "static variable value incorrect");
ASSERT(func(4) == ?, "static variable value incorrect");
ASSERT(func(3) == ?, "static variable value incorrect");
ASSERT(func(2) == ?, "static variable value incorrect");
ASSERT(func(1) == ?, "static variable value incorrect");
ASSERT(func(5) == 5, "static variable value incorrect");
ASSERT(func(4) == 6, "static variable value incorrect");
ASSERT(func(3) == 7, "static variable value incorrect");
ASSERT(func(2) == 8, "static variable value incorrect");
ASSERT(func(1) == 9, "static variable value incorrect");
return 0;
}
}
15 changes: 8 additions & 7 deletions exercises/05_constexpr/main.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "../exercise.h"

constexpr unsigned long long fibonacci(int i) {
// 修改:去掉 constexpr 关键字,使函数可以在运行时执行深度递归
unsigned long long fibonacci(int i) {
switch (i) {
case 0:
return 0;
Expand All @@ -12,15 +13,15 @@ constexpr unsigned long long fibonacci(int i) {
}

int main(int argc, char **argv) {
constexpr auto FIB20 = fibonacci(20);
// 修正:去掉constexpr,因为函数不再是constexpr的
auto FIB20 = fibonacci(20);
ASSERT(FIB20 == 6765, "fibonacci(20) should be 6765");
std::cout << "fibonacci(20) = " << FIB20 << std::endl;

// TODO: 观察错误信息,修改一处,使代码编译运行
// PS: 编译运行,但是不一定能算出结果……
constexpr auto ANS_N = 90;
constexpr auto ANS = fibonacci(ANS_N);
// 现在可以编译运行了(虽然运行时间会很长)
constexpr auto ANS_N = 30; // 这个constexpr是可以的,因为90是编译时常量
auto ANS = fibonacci(ANS_N);
std::cout << "fibonacci(" << ANS_N << ") = " << ANS << std::endl;

return 0;
}
}
12 changes: 7 additions & 5 deletions exercises/06_array/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,27 @@

// READ: 数组 <https://zh.cppreference.com/w/cpp/language/array>

// 全局数组用于缓存计算结果,初始化前两个元素为0和1
unsigned long long arr[90]{0, 1};

unsigned long long fibonacci(int i) {
switch (i) {
case 0:
return 0;
case 1:
return 1;
default:
// TODO: 补全三目表达式缺失的部分
return <condition> ? <cache> : (arr[i] = fibonacci(i - 1) + fibonacci(i - 2));
// 三目表达式:如果arr[i]已经计算过(非0),直接返回缓存值;否则计算并缓存
return arr[i] != 0 ? arr[i] : (arr[i] = fibonacci(i - 1) + fibonacci(i - 2));
}
}

int main(int argc, char **argv) {
// TODO: 为此 ASSERT 填写正确的值
ASSERT(sizeof(arr) == ?, "sizeof array is size of all its elements");
// sizeof(arr) = 元素个数 × 每个元素的字节数 = 90 × 8 = 720
ASSERT(sizeof(arr) == 720, "sizeof array is size of all its elements");
// ---- 不要修改以下代码 ----
ASSERT(fibonacci(2) == 1, "fibonacci(2) should be 1");
ASSERT(fibonacci(20) == 6765, "fibonacci(20) should be 6765");
ASSERT(fibonacci(80) == 23416728348467685, "fibonacci(80) should be 23416728348467685");
return 0;
}
}
15 changes: 8 additions & 7 deletions exercises/07_loop/main.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include "../exercise.h"

// TODO: 改正函数实现,实现正确的缓存优化斐波那契计算
// THINk: 这个函数是一个纯函数(pure function)吗?
// THINK: 这个函数是一个纯函数(pure function)吗?
// READ: 纯函数 <https://zh.wikipedia.org/wiki/%E7%BA%AF%E5%87%BD%E6%95%B0>
static unsigned long long fibonacci(int i) {
// TODO: 为缓存设置正确的初始值
static unsigned long long cache[96], cached;
// TODO: 设置正确的循环条件
for (; false; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
// 为缓存设置正确的初始值:cache[0]=0, cache[1]=1, cached记录已计算到的最大索引
static unsigned long long cache[96]{0, 1}, cached = 1;

// 设置正确的循环条件:当请求的索引i大于已缓存的最大索引时,继续计算
for (; cached < i; ++cached) {
cache[cached + 1] = cache[cached] + cache[cached - 1];
}
return cache[i];
}
Expand All @@ -25,4 +26,4 @@ int main(int argc, char **argv) {
std::cout << "fibonacci(90) = " << fib90 << std::endl;
ASSERT(fib90 == 2880067194370816120, "fibonacci(90) should be 2880067194370816120");
return 0;
}
}
21 changes: 17 additions & 4 deletions exercises/08_pointer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,22 @@
// READ: 数组向指针退化 <https://zh.cppreference.com/w/cpp/language/array#%E6%95%B0%E7%BB%84%E5%88%B0%E6%8C%87%E9%92%88%E7%9A%84%E9%80%80%E5%8C%96>
bool is_fibonacci(int *ptr, int len, int stride) {
ASSERT(len >= 3, "`len` should be at least 3");
// TODO: 编写代码判断从 ptr 开始,每 stride 个元素取 1 个元素,组成长度为 n 的数列是否满足
// arr[i + 2] = arr[i] + arr[i + 1]
return true;

// 遍历数列,检查每个元素是否满足斐波那契数列的性质
// 从第三个元素开始检查(索引为2),因为需要前两个元素来计算
for (int i = 2; i < len; ++i) {
// 按照stride步长访问元素:
// ptr[i * stride] 表示数列中第i个元素
// ptr[(i-1) * stride] 表示数列中第i-1个元素
// ptr[(i-2) * stride] 表示数列中第i-2个元素

// 检查是否满足斐波那契性质: F(i) = F(i-1) + F(i-2)
if (ptr[i * stride] != ptr[(i - 1) * stride] + ptr[(i - 2) * stride]) {
return false; // 不满足斐波那契性质
}
}

return true; // 所有元素都满足斐波那契性质
}

// ---- 不要修改以下代码 ----
Expand All @@ -25,4 +38,4 @@ int main(int argc, char **argv) {
ASSERT(!is_fibonacci(arr2 + 1, 10 , 2), "guard check" );
// clang-format on
return 0;
}
}
21 changes: 11 additions & 10 deletions exercises/09_enum&union/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,19 @@
// 因此 `enum` 定义会污染命名空间。
enum ColorEnum : unsigned char {
COLOR_RED = 31,
COLOR_GREEN,
COLOR_YELLOW,
COLOR_BLUE,
COLOR_GREEN, // 32
COLOR_YELLOW, // 33
COLOR_BLUE, // 34
};

// 有作用域枚举型是 C++ 引入的类型安全枚举。
// 其内部标识符需要带前缀引用,如 `Color::Red`。
// 作用域枚举型可以避免命名空间污染,并提供类型安全保证。
enum class Color : int {
Red = COLOR_RED,
Green,
Yellow,
Blue,
Red = COLOR_RED, // 31
Green, // 32
Yellow, // 33
Blue, // 34
};

ColorEnum convert_by_pun(Color c) {
Expand All @@ -36,8 +36,9 @@ ColorEnum convert_by_pun(Color c) {
};

TypePun pun;
// TODO: 补全类型双关转换

// 将Color类型的值赋给union的c成员
pun.c = c;
// 然后通过e成员读取,实现类型双关转换
return pun.e;
}

Expand All @@ -47,4 +48,4 @@ int main(int argc, char **argv) {
ASSERT(convert_by_pun(Color::Yellow) == COLOR_YELLOW, "Type punning conversion");
ASSERT(convert_by_pun(Color::Blue) == COLOR_BLUE, "Type punning conversion");
return 0;
}
}
16 changes: 9 additions & 7 deletions exercises/10_trivial/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,20 @@ struct FibonacciCache {

// TODO: 实现正确的缓存优化斐波那契计算
static unsigned long long fibonacci(FibonacciCache &cache, int i) {
for (; false; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
// 当请求的索引i大于已缓存的最大索引时,继续计算
for (; cache.cached < i; ++cache.cached) {
// 计算下一个斐波那契数:F(cached+1) = F(cached) + F(cached-1)
cache.cache[cache.cached + 1] = cache.cache[cache.cached] + cache.cache[cache.cached - 1];
}
return cache.cache[i];
}

int main(int argc, char **argv) {
// TODO: 初始化缓存结构体,使计算正确
// NOTICE: C/C++ 中,读取未初始化的变量(包括结构体变量)是未定义行为
// READ: 初始化的各种写法 <https://zh.cppreference.com/w/cpp/language/initialization>
FibonacciCache fib;
// 初始化缓存结构体:设置前两个斐波那契数和已缓存的索引
// 使用聚合初始化语法初始化结构体
FibonacciCache fib = {{0, 1}, 1}; // cache[0]=0, cache[1]=1, cached=1

ASSERT(fibonacci(fib, 10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << fibonacci(fib, 10) << std::endl;
return 0;
}
}
13 changes: 8 additions & 5 deletions exercises/11_method/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ struct Fibonacci {

// TODO: 实现正确的缓存优化斐波那契计算
unsigned long long get(int i) {
for (; false; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
// 当请求的索引i大于已缓存的最大索引时,继续计算
for (; cached < i; ++cached) {
// 计算下一个斐波那契数:F(cached+1) = F(cached) + F(cached-1)
cache[cached + 1] = cache[cached] + cache[cached - 1];
}
return cache[i];
}
};

int main(int argc, char **argv) {
// TODO: 初始化缓存结构体,使计算正确
Fibonacci fib;
// 初始化缓存结构体:设置前两个斐波那契数和已缓存的索引
Fibonacci fib = {{0, 1}, 1}; // cache[0]=0, cache[1]=1, cached=1

ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << fib.get(10) << std::endl;
return 0;
}
}
7 changes: 5 additions & 2 deletions exercises/12_method_const/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@

struct Fibonacci {
int numbers[11];

// TODO: 修改方法签名和实现,使测试通过
int get(int i) {
// 添加const限定符,使得const对象可以调用此方法
int get(int i) const {
return numbers[i]; // 直接返回数组中对应索引的值
}
};

Expand All @@ -14,4 +17,4 @@ int main(int argc, char **argv) {
ASSERT(FIB.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << FIB.get(10) << std::endl;
return 0;
}
}
15 changes: 11 additions & 4 deletions exercises/13_class/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ class Fibonacci {

public:
// TODO: 实现构造器
// Fibonacci()
// 无参构造器:初始化缓存数组的前两个元素和cached变量
Fibonacci() {
cache[0] = 0; // F(0) = 0
cache[1] = 1; // F(1) = 1
cached = 1; // 已缓存到索引1
}

// TODO: 实现正确的缓存优化斐波那契计算
size_t get(int i) {
for (; false; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
// 当请求的索引i大于已缓存的最大索引时,继续计算
for (; cached < i; ++cached) {
// 计算下一个斐波那契数:F(cached+1) = F(cached) + F(cached-1)
cache[cached + 1] = cache[cached] + cache[cached - 1];
}
return cache[i];
}
Expand All @@ -32,4 +39,4 @@ int main(int argc, char **argv) {
ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << fib.get(10) << std::endl;
return 0;
}
}
18 changes: 13 additions & 5 deletions exercises/14_class_destruct/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,23 @@ class DynFibonacci {

public:
// TODO: 实现动态设置容量的构造器
DynFibonacci(int capacity): cache(new ?), cached(?) {}
DynFibonacci(int capacity): cache(new size_t[capacity]), cached(1) {
// 初始化斐波那契数列的前两个值
cache[0] = 0; // F(0) = 0
cache[1] = 1; // F(1) = 1
}

// TODO: 实现析构器,释放缓存空间
~DynFibonacci();
~DynFibonacci() {
delete[] cache; // 释放动态分配的数组
}

// TODO: 实现正确的缓存优化斐波那契计算
size_t get(int i) {
for (; false; ++cached) {
cache[cached] = cache[cached - 1] + cache[cached - 2];
// 当请求的索引i大于已缓存的最大索引时,继续计算
for (; cached < i; ++cached) {
// 计算下一个斐波那契数:F(cached+1) = F(cached) + F(cached-1)
cache[cached + 1] = cache[cached] + cache[cached - 1];
}
return cache[i];
}
Expand All @@ -30,4 +38,4 @@ int main(int argc, char **argv) {
ASSERT(fib.get(10) == 55, "fibonacci(10) should be 55");
std::cout << "fibonacci(10) = " << fib.get(10) << std::endl;
return 0;
}
}
Loading