banner
Nanomoa

Nanomoa's Blog

"Bytes and Brackets: My Journey in Go and C++ Exploration."
github
zhihu
telegram
twitter

CS106L 2024年春の課題

コースホームページ: CS106L

宿題リスト#

宿題番号宿題タイトル宿題リンク
Assignment 1SimpleEnroll完了する
Assignment 2Marriage Pact完了する
Assignment 3Make a class!完了する
Assignment 4Weather Forecast完了する
.........

Assignment 1: SimpleEnroll#

現在はできません。この宿題のネットワークドライブは外部に公開されていません(おそらく

Assignment 2: Marriage Pact#

知識点: STL のコンテナとポインタ

概要#

開始コード:

  • main.cpp - ソースコードファイル
  • students.txt - すべての学生の名前、一行に一つ、形式は Xxxxx Xxxxx

この宿題では、すべての名前の中から自分の名前と一致するものを見つける必要があります。名前のイニシャルが自分の名前と一致する場合にのみ一致し、その後、任意の戦略を用いてすべての一致項目から唯一の項目を見つけます。

パート 1: すべての応募者を取得#

この部分では、ファイル内のすべての名前を std::set<std::string> または std::unordered_set<std::string> に読み込む必要があります。

考え方:

std::ifstreamstd::stringstream を組み合わせれば良いです。

コード:

std::set<std::string> get_applicants(std::string filename) {
    std::set<std::string> result;

    std::ifstream ifs(filename);

    if (ifs.is_open()) {
        std::stringstream ss;
        ss << ifs.rdbuf();

        std::string line;
        while (std::getline(ss, line)) {
            result.insert(line);
        }
    }

    return result;
}

パート 2: 一致を見つける#

この部分では、すべての一致項目を std::queue<const std::string*> に格納する必要があります。

考え方:

std::set は順序があり二分探索が可能です。私の名前のイニシャルはTGなので、まず T で始まる名前の左右の境界を二分探索で見つけ、その後その範囲を遍歴して一致項目を見つけます。

コード:

std::queue<const std::string*> find_matches(std::set<std::string> &students) {
    std::queue<const std::string*> result;

    std::string Prefix("T");
    auto itLeft = students.lower_bound(Prefix);

    std::string nextPrefix("U");
    auto itRight = students.lower_bound(nextPrefix);

    for (auto it = itLeft; it != itRight; it++) {
        const std::string& name = *it;

        std::stringstream ss(name);

        std::string first, last;
        ss >> first >> last;

        if(last[0] != 'G') {
            continue;
        }

        result.push(&name);
    }

    return result;
}


次に、一致項目から唯一の項目を取り出す必要があります。ここではランダムに一つを選びます。

完全なコード:

/* 
Assignment 2: Marriage Pact

この宿題では、コンテナとポインタを使用してあなたの真実の愛を見つけることを求めています。
2つの部分があります: get_applicants と find_matches を実装します。

2024年2月1日午後11時59分までにPaperlessに提出してください。
*/

#include <iostream>
#include <string>
#include <queue>
#include <set>
#include <fstream>
#include <sstream>
#include <random>

std::set<std::string> get_applicants(std::string filename) {
    std::set<std::string> result;

    std::ifstream ifs(filename);

    if (ifs.is_open()) {
        std::stringstream ss;
        ss << ifs.rdbuf();

        std::string line;
        while (std::getline(ss, line)) {
            result.insert(line);
        }
    }

    return result;
}

std::queue<const std::string*> find_matches(std::set<std::string> &students) {
    std::queue<const std::string*> result;

    std::string Prefix("T");
    auto itLeft = students.lower_bound(Prefix);

    std::string nextPrefix("U");
    auto itRight = students.lower_bound(nextPrefix);

    for (auto it = itLeft; it != itRight; it++) {
        const std::string& name = *it;

        std::stringstream ss(name);

        std::string first, last;
        ss >> first >> last;

        if(last[0] != 'G') {
            continue;
        }

        result.push(&name);
    }

    return result;
}



int main() {
    auto students = get_applicants("students.txt");

    for (const auto& name : students) {
        std::cout << name << std::endl;
    }

    auto matches = find_matches(students);

    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(1, static_cast<int>(matches.size()));
    int rand_int = distribution(generator);

    int position = 1;
    std::string trueLove;

    while (!matches.empty()) {
        const std::string* name = matches.front();
        matches.pop();

        trueLove = *name;

        if (position == rand_int) {
            break;
        }

        position++;
    }

    std::cout << "あなたの真実の愛は " << trueLove << '\n';

    return 0;
}

Assignment 3: クラスを作成する#

知識点:クラス、コンストラクタのオーバーロード、const の正しさ

概要#

開始コード:

  • class.h - クラスの定義ファイル(ヘッダファイル)
  • class.cpp - クラスの実装
  • main.cpp - 主要ファイル(インスタンス化して実行)

この宿題では、自分でクラスを実装し、以下の要件を満たす必要があります:

  1. カスタムコンストラクタを持つこと
  2. デフォルトコンストラクタを持つこと
  3. プライベートメンバーを持つこと
  4. パブリックメンバーを持つこと
  5. 少なくとも 1 つのgetterメソッドと 1 つのsetterメソッドを持つこと

const の正しさ#

const の正しさは、変更すべきでない / 変更する必要のない値を変更しないようにconstキーワードを使用することを奨励する原則であり、エラーを減らし、コードの可読性(明確さ)を向上させ、コンパイラの最適化の機会を得るのに役立ちます。

この宿題では、主に getter メソッドおよび setter メソッドの引数に反映されます。

コード#

  • class.h
// 空のヘッダファイル

#include <string>

class Student {
private:
    std::string name;
    int age;
    std::string id;
    std::string dept;
public:
    Student();

    Student(const std::string& _name, int _age, const std::string& _id, const std::string& _dept);

    void setName(const std::string& _name);

    const std::string& getName() const;

    void setAge(int _age);

    int getAge() const;

    void setId(const std::string& _id);

    const std::string& getId() const;

    void setDept(const std::string& _dept);

    const std::string& getDept() const;
};
  • class.cpp
// 空のcppファイル

#include "class.h"

Student::Student() = default;

Student::Student(const std::string& _name, int _age, const std::string& _id, const std::string& _dept) {
    this->name = _name;
    this->age = _age;
    this->id = _id;
    this->dept = _dept;
}

void Student::setName(const std::string& _name) {
    this->name = _name;
}

const std::string &Student::getName() const {
    return this->name;
}

void Student::setAge(int _age) {
    this->age = _age;
}

int Student::getAge() const {
    return this->age;
}

void Student::setId(const std::string &_id) {
    this->id = _id;
}

const std::string &Student::getId() const {
    return this->id;
}

void Student::setDept(const std::string &_dept) {
    this->dept = _dept;
}

const std::string &Student::getDept() const {
    return this->dept;
}
  • main.cpp
#include <memory>
#include <iostream>
#include "class.h"

/*
 * 宿題 3: クラスを作成する!
 * 要件:
 * カスタムコンストラクタを持つこと 
 * デフォルトコンストラクタを持つこと 
    - すなわち、コンストラクタのオーバーロード
 * プライベートメンバー(関数および/または変数)を持つこと 
 * パブリックメンバー(関数)を持つこと 
 * 少なくとも1つのgetter関数を持つこと 
 * 少なくとも1つのsetter関数を持つこと 
 */

int main() {
  // クラスを初期化してこのファイルを実行
  auto stu = std::make_unique<Student>("Nanomoa", 20, "12345678", "Computer Science");

  std::cout << "名前: " << stu->getName() << '\n';
  std::cout << "年齢: " << stu->getAge() << '\n';
  std::cout << "ID: " << stu->getId() << '\n';
  std::cout << "学科: " << stu->getDept() << '\n';

  // または
  auto stu1 = std::make_unique<Student>();

  stu1->setName("Nanomoa");
  stu1->setAge(20);
  stu1->setId("12345678");
  stu1->setDept("Computer Science");

  std::cout << "名前: " << stu1->getName() << '\n';
  std::cout << "年齢: " << stu1->getAge() << '\n';
  std::cout << "ID: " << stu1->getId() << '\n';
  std::cout << "学科: " << stu1->getDept() << '\n';

  return 0;
}

Assignment 4: 天気予報#

知識点:テンプレート関数、ラムダ

概要#

開始コード:

  • main.cpp 主要コードファイル
  • output.txt 出力ファイル

ある週の毎日の異なる時間帯の華氏温度が与えられています。この宿題では、template functionlambdaを使用していくつかの処理を行う必要があります。

パート 1: 温度変換器#

Template Functionを使用して関数 convert_f_to_c を実装し、華氏温度を摂氏温度に変換し、double型の値を返します。

注意: 入力される華氏温度の型は不明です。

変換公式: (Fahrenheit32)×5÷9( Fahrenheit - 32) \times 5 \div 9

コード:

template<typename Type>
double convert_f_to_c(Type f) {
    return (static_cast<double>(f) - 32) * 5 / 9;
}

パート 2: 週間予報#

関数 get_forecast を実装して結果を集計します。

関数テンプレート:

template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
  // TODO
}

注意: ここでの fnlambdaを引数として受け取る必要があります。

私たちは毎日を遍歴し、その後fnを呼び出して結果を格納するだけです。

コード:

template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
    std::vector<double> result;
    result.reserve(readings.size());
    for (const auto& day : readings) {
        result.push_back(fn(day));
    }
    return result;
}

パート 3: すべてをまとめる#

main関数内で上記の実装した関数を呼び出し、以下の機能を完成させる必要があります:

  1. readingsを摂氏温度に変換し、output.txtに出力する
  2. 毎日の最高温度を集計し、output.txtに出力する
  3. 毎日の最低温度を集計し、output.txtに出力する
  4. 毎日の平均温度を集計し、output.txtに出力する

その中で2~4は、対応するlambdaを引数としてget_forecast関数に渡す必要があります。

コード:

    // TODO: 温度を摂氏に変換し、output.txtに出力
    for (auto& vec : readings) {
        for (auto& item : vec) {
            item = convert_f_to_c(item);
        }
    }

    std::ofstream ofs("output.txt");
    if (ofs.is_open()) {
        for (auto& vec : readings) {
            for (auto& item : vec) {
                ofs << item << " ";
            }
            ofs << '\n';
        }
        ofs.close();
    }

    // TODO: 毎日の最高温度を見つけてoutput.txtに出力
    auto maximum_temps = [](const std::vector<double>& day) -> double {
        return *std::max_element(day.begin(), day.end());
    };

    auto max_temps = get_forecast(readings, maximum_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : max_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

    // TODO: 毎日の最低温度を見つけてoutput.txtに出力
    auto minimum_temps = [](const std::vector<double>& day) -> double {
        return *std::min_element(day.begin(), day.end());
    };

    auto min_temps = get_forecast(readings, minimum_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : min_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

    // TODO: 毎日の平均温度を見つけてoutput.txtに出力
    auto average_temps = [](const std::vector<double>& day) -> double {
        double sum = std::accumulate(day.begin(), day.end(), 0.0);
        return sum / static_cast<double>(day.size());
    };

    auto avg_temps = get_forecast(readings, average_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : avg_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

完全なコード:#

/* 
Assignment 4: 天気予報

この宿題では、テンプレート関数とラムダを使用してスタンフォードデイリーで最高の天気予報士になることを目指します。
PDFの宿題の詳細を必ず読んでください。

2024年5月10日午後11時59分までにPaperlessに提出してください。
*/

// TODO: STLから役立つものをインポートする!
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <numeric>


// TODO: convert_f_to_c関数をここに書いてください。常に
// doubleを返すテンプレート関数であることを忘れないでください。
template<typename Type>
double convert_f_to_c(Type f) {
    return (static_cast<double>(f) - 32) * 5 / 9;
}

template<typename Function>
std::vector<double> get_forecast(std::vector<std::vector<double>> readings, Function fn) {
    std::vector<double> result;
    result.reserve(readings.size());
    for (const auto& day : readings) {
        result.push_back(fn(day));
    }
    return result;
}

int main() {
    std::vector<std::vector<double>> readings = {
            {70, 75, 80, 85, 90},
            {60, 65, 70, 75, 80},
            {50, 55, 60, 65, 70},
            {40, 45, 50, 55, 60},
            {30, 35, 40, 45, 50},
            {50, 55, 61, 65, 70},
            {40, 45, 50, 55, 60}
    };

    // TODO: 温度を摂氏に変換し、output.txtに出力
    for (auto& vec : readings) {
        for (auto& item : vec) {
            item = convert_f_to_c(item);
        }
    }

    std::ofstream ofs("output.txt");
    if (ofs.is_open()) {
        for (auto& vec : readings) {
            for (auto& item : vec) {
                ofs << item << " ";
            }
            ofs << '\n';
        }
        ofs.close();
    }

    // TODO: 毎日の最高温度を見つけてoutput.txtに出力
    auto maximum_temps = [](const std::vector<double>& day) -> double {
        return *std::max_element(day.begin(), day.end());
    };

    auto max_temps = get_forecast(readings, maximum_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : max_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

    // TODO: 毎日の最低温度を見つけてoutput.txtに出力
    auto minimum_temps = [](const std::vector<double>& day) -> double {
        return *std::min_element(day.begin(), day.end());
    };

    auto min_temps = get_forecast(readings, minimum_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : min_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

    // TODO: 毎日の平均温度を見つけてoutput.txtに出力
    auto average_temps = [](const std::vector<double>& day) -> double {
        double sum = std::accumulate(day.begin(), day.end(), 0.0);
        return sum / static_cast<double>(day.size());
    };

    auto avg_temps = get_forecast(readings, average_temps);

    ofs.open("output.txt", std::ios_base::app);
    if (ofs.is_open()) {
        for (auto& item : avg_temps) {
            ofs << item << " ";
        }
        ofs << '\n';
        ofs.close();
    }

    return 0;
}
読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。