banner
Nanomoa

Nanomoa's Blog

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

CS106L Spring 2024 Assignment

Course Homepage: CS106L

Assignment List#

Assignment NumberAssignment TitleAssignment Link
Assignment 1SimpleEnrollGo to complete
Assignment 2Marriage PactGo to complete
Assignment 3Make a class!Go to complete
Assignment 4Weather ForecastGo to complete
.........

Assignment 1: SimpleEnroll#

Currently unavailable, this assignment's cloud storage is not open to the public (probably)

Assignment 2: Marriage Pact#

Key Points: STL's containers and pointers

Introduction#

start code:

  • main.cpp - Source code file
  • students.txt - Names of all students, one per line, in the form of Xxxxx Xxxxx

This assignment requires finding a match from all names that corresponds to your own name, only matching when the initials of a name are the same as your own, and then using any strategy to find a unique match from all matches.

Part 1: Get all applicants#

This part requires reading all names from the file into std::set<std::string> or std::unordered_set<std::string>.

Approach:

Using std::ifstream in conjunction with std::stringstream.

Code:

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;
}

Part 2: Find matches#

This part requires finding all matches and placing them into std::queue<const std::string*>.

Approach:

std::set is ordered and can be binary searched. My initials are TG, so first, I will binary search to find the left and right boundaries of names starting with T, and then traverse that range to find matches.

Code:

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;
}


Then, I will randomly select one unique match from the matches.

Complete Code:

/* 
Assignment 2: Marriage Pact

This assignment asks you to discover your one true love using containers and pointers.
There are two parts: implement get_applicants and find_matches.

Submit to Paperless by 11:59pm on 2/1/2024.
*/

#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 << "Your true love is " << trueLove << '\n';

    return 0;
}

Assignment 3: Make a Class#

Key Points: class, constructor overloading, const-correctness

Introduction#

start code:

  • class.h - Class definition file (header file)
  • class.cpp - Class implementation
  • main.cpp - Main file (instantiation and execution)

This assignment requires you to implement a class that meets the following requirements:

  1. Must have a custom constructor
  2. Must have a default constructor
  3. Must have private members
  4. Must have public members
  5. Must have at least one getter method and one setter method

const-correctness#

const-correctness is a principle that encourages the use of the const keyword to prevent changing values that should not/need not be changed, helping to reduce errors and improve code readability (clarity), as well as gaining opportunities for compiler optimization.

In this assignment, it is mainly reflected in the parameters of getter and setter methods.

Code#

  • class.h
// Blank header file

#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
// Blank cpp file

#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"

/*
 * Assigment 3: Make a class!
 * Requirements:
 * Must have a custom constructor 
 * Must have a default constructor 
    - i.e. constructor overloading
 * Must have private members (functions and/or variables) 
 * Must have public members (functions) 
 * Must have at least one getter function 
 * Must have at least one setter function 
 */

int main() {
  // initialize class and run this file
  auto stu = std::make_unique<Student>("Nanomoa", 20, "12345678", "Computer Science");

  std::cout << "Name: " << stu->getName() << '\n';
  std::cout << "Age: " << stu->getAge() << '\n';
  std::cout << "ID: " << stu->getId() << '\n';
  std::cout << "Dept: " << stu->getDept() << '\n';

  // or
  auto stu1 = std::make_unique<Student>();

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

  std::cout << "Name: " << stu1->getName() << '\n';
  std::cout << "Age: " << stu1->getAge() << '\n';
  std::cout << "ID: " << stu1->getId() << '\n';
  std::cout << "Dept: " << stu1->getDept() << '\n';

  return 0;
}

Assignment 4: Weather Forecast#

Key Points: template function, lambda

Introduction#

start code:

  • main.cpp Main code file
  • output.txt Output file

Given the Fahrenheit temperatures at different times of the day for a week, this assignment requires using template function and lambda to process them.

Part 1: Temperature Converter#

Use Template Function to implement the function convert_f_to_c, which converts Fahrenheit temperatures to Celsius, returning a double type value.

Note: The type of the input Fahrenheit temperature is unknown.

Conversion formula: (Fahrenheit32)×5÷9( Fahrenheit - 32) \times 5 \div 9

Code:

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

Part 2: The Weekly Forecast#

Complete the implementation of the function get_forecast to perform result statistics.

Function template:

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

Note: The fn here needs to accept a lambda as a parameter.

We just need to iterate through each day, then call fn to calculate and store the result.

Code:

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;
}

Part 3: Putting it all together#

We need to call the above-implemented functions in the main function to achieve the following functionalities:

  1. Convert readings to Celsius and output to output.txt
  2. Calculate the highest temperature for each day and output to output.txt
  3. Calculate the lowest temperature for each day and output to output.txt
  4. Calculate the average temperature for each day and output to output.txt

Among which, 2~4 need to implement corresponding lambda to be passed to the get_forecast function.

Code:

    // TODO: Convert temperatures to Celsius and output to 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: Find the maximum temperature for each day and output to 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: Find the minimum temperature for each day and output to 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: Find the average temperature for each day and output to 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();
    }

Complete Code:#

/* 
Assignment 4: Weather Forecast

This assignment works with template functions and lambdas to become the best weather forecaster
at the Stanford Daily. Be sure to read the assignment details in the PDF.

Submit to Paperless by 11:59pm on 5/10/2024.
*/

// TODO: import anything from the STL that might be useful!
#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
#include <numeric>


// TODO: write convert_f_to_c function here. Remember it must be a template function that always returns
// a 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: Convert temperatures to Celsius and output to 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: Find the maximum temperature for each day and output to 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: Find the minimum temperature for each day and output to 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: Find the average temperature for each day and output to 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;
}
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.