Skip to content

Commit 3d5e9ec

Browse files
release: assignment2
1 parent 8947475 commit 3d5e9ec

File tree

11 files changed

+1724
-0
lines changed

11 files changed

+1724
-0
lines changed

assignment2/README.md

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<p align="center">
2+
<img src="docs/marriage_pact.png" alt="Marriage Pact Logo" />
3+
</p>
4+
5+
# Assignment 2: Marriage Pact
6+
7+
Due Friday, May 2nd at 11:59PM
8+
9+
## Overview
10+
11+
Happy assignment 2! This is meant to be a very short and sweet bit of practice to get you started working with the STL's containers and pointers.
12+
13+
These are the files you need to care about:
14+
15+
- `main.cpp`: All your code goes here 😀!
16+
- `short_answer.txt`: Short answer responses go here 📝!
17+
18+
To download the starter code for this assignment, please see the instructions for [**Getting Started**](../README.md#getting-started) on the course assignments repository.
19+
20+
## Running your code
21+
22+
To run your code, first you'll need to compile it. Open up a terminal (if you are using VSCode, hit <kbd>Ctrl+\`</kbd> or go to **Terminal > New Terminal** at the top). Then make sure that you are in the `assignment2/` directory and run:
23+
24+
```sh
25+
g++ -std=c++20 main.cpp -o main
26+
```
27+
28+
Assuming that your code compiles without any compiler errors, you can now do:
29+
30+
```sh
31+
./main
32+
```
33+
34+
which will actually run the `main` function in `main.cpp`.
35+
36+
As you are following the instructions below, we recommend intermittently compiling/testing with the autograder as a way to make sure you're on the right track!
37+
38+
> [!NOTE]
39+
>
40+
> ### Note for Windows
41+
>
42+
> On Windows, you may need to compile your code using
43+
>
44+
> ```sh
45+
> g++ -static-libstdc++ -std=c++20 main.cpp -o main
46+
> ```
47+
>
48+
> in order to see output. Also, the output executable may be called `main.exe`, in which case you'll run your code with:
49+
>
50+
> ```sh
51+
> ./main.exe
52+
> ```
53+
54+
## Part 0: Setup
55+
56+
Welcome to the Marriage Pact! Before you begin, we'll need to know your name. Please change the constant `kYourName` at the top of `main.cpp` from `"STUDENT TODO"` to your full name (with a space between first and last).
57+
58+
## Part 1: Get all applicants
59+
60+
You’ve been waiting for days to get your Marriage Pact initials this year, and they’ve finally arrived in your inbox! This year, they’re implementing a new rule: your match MUST share your own initials to be eligible. However, even after talking about it for hours with your friends, you have no idea who your match could be! There are thousands of students on campus, and you can’t just go through the whole roster by hand to draft up a list of your potential soulmates. Fortunately enough for you, you’re in CS106L, and you remember that C++ has a pretty quick method of going through collected, similar information – containers!
61+
62+
We’ve included a `.txt` file of all of the (fictional) students who signed up for The Marriage Pact this year (`students.txt`). Each line includes the first and last name of the student. You will first write the function `get_applicants`:
63+
64+
> [!IMPORTANT]
65+
>
66+
> ### `get_applicants`
67+
>
68+
> From the `.txt` file, parse all of the names into a set. Each line contained in the file named `filename` is a single applicant's name. In your implementation, you are free to choose between an ordered (`std::set`) and unordered set (`std::unordered_set`) as you wish! If you do choose to use an unordered set, please change the relevant function definitions!
69+
70+
Additionally, please answer the following short answer question in `short_answer.txt`:
71+
72+
> [!IMPORTANT]
73+
>
74+
> ### `short_answer.txt`
75+
>
76+
> **Q1:** It is your choice to use either an ordered or unordered set. In a few sentences, what are some of the tradeoffs between the two? Additionally, please give an example (that has not been shown in lecture) of a valid hash function that could be used to hash student names for an unordered set.
77+
78+
> [!NOTE]
79+
> All names appearing in this assignment are fictitious. Any resemblance to real persons, living or dead, is purely coincidental.
80+
81+
## Part 2: Find matches
82+
83+
Great detective work! Now that you’ve narrowed down your list of potential soulmates, it’s time to put it to the test. After a long day of acapella and consulting club meetings, you return to your dorm to learn from your roommate that there is a mixer for Marriage Pact matches at Main Quad that night! Your best chance of finding true love is imminent — if only you can get out of your Ultimate Frisbee practice. Quickly, you decide to interview everyone who shares your initials at the mixer, and you get to work coding up a function that will compile the order for you automatically.
84+
85+
For this section, you will write the functions `find_matches` and `get_match`:
86+
87+
> [!IMPORTANT]
88+
>
89+
> ### `find_matches`
90+
>
91+
> From the set `students` (generated in the previous part), take all names that share initials with the parameter `name` and place pointers to them in a new `std::queue`.
92+
>
93+
> - If you’re having trouble figuring out how to iterate through a set, it could be helpful to look back over [Thursday’s lecture on iterators and pointers](https://office365stanford-my.sharepoint.com/:p:/g/personal/jtrb_stanford_edu/EbOKUV784rBHrO3JIhUSAUgBvuIGn5rSU8h3xbq-Q1JFfQ?e=BlZwa7).
94+
> - You will need to be familiar with the operations of a `std::queue` for this part. Take a look at cppreference's documentation [here](https://en.cppreference.com/w/cpp/container/queue).
95+
> - Hint: It might help to define a helper function that computes the initials of some student's name. Then you can use that helper function to compare the initials of `name` with the initials of each name in `students`.
96+
97+
From here please implement the function `get_match` to find your “one true match.”:
98+
99+
> [!IMPORTANT]
100+
>
101+
> ### `get_match`
102+
>
103+
> Gets your “one true match” from the queue of all possible matches. This can be determined as you see fit; choose some method of acquiring one student from the queue, ideally something with a bit more thought than a single `pop()`, but it doesn’t have to be particularly complicated! Consider random values or other methods of selection.
104+
>
105+
> If your initials have no matches in the dataset, print `“NO MATCHES FOUND.”` Better luck next year 😢
106+
107+
Afterwards, answer the following question in `short_answer.txt`:
108+
109+
> [!IMPORTANT]
110+
>
111+
> ### `short_answer.txt`
112+
>
113+
> **Q2:** Note that we are saving pointers to names in the queue, not names themselves. Why might this be desired in this problem? What happens if the original set where the names are stored goes out of scope and the pointers are referenced?
114+
115+
## 🚀 Submission Instructions
116+
117+
Before you submit the assignment, please fill out this [short feedback form](https://forms.gle/jTQSpVjesp1F6MEp6). **Completion of the form is required to receive credit for the assignment.** After filling out the form, please upload the files to Paperless under the correct assignment heading.
118+
119+
Your deliverable should be:
120+
121+
- `main.cpp`
122+
- `short_answer.txt`
123+
124+
You may resubmit as many times as you'd like before the deadline.
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
from utils import Autograder
2+
import os
3+
4+
PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), os.pardir))
5+
AUTOGRADER_DIR = os.path.join(PATH, "autograder")
6+
TEST_FILE_PATH = os.path.join(PATH, "students.txt")
7+
8+
9+
def get_initials(name):
10+
parts = name.split()
11+
if len(parts) == 2:
12+
return parts[0][0] + parts[1][0]
13+
return None
14+
15+
16+
def read_students_file(filename):
17+
with open(filename, "r") as file:
18+
return {line.strip() for line in file.readlines()}
19+
20+
21+
def test_applicants_set():
22+
expected_possible_matches = read_students_file(TEST_FILE_PATH)
23+
24+
student_output_set_path = os.path.join(AUTOGRADER_DIR, "student_output/set.txt")
25+
26+
with open(student_output_set_path, "r") as possible_matches_file:
27+
possible_matches = {line.strip() for line in possible_matches_file.readlines()}
28+
29+
if possible_matches != expected_possible_matches:
30+
raise RuntimeError(
31+
f"❌ Output does not match expected set of possible matches. Diff: {possible_matches ^ expected_possible_matches}"
32+
)
33+
34+
35+
def test_match():
36+
all_students = read_students_file(TEST_FILE_PATH)
37+
38+
student_output_match_path = os.path.join(AUTOGRADER_DIR, "student_output/match.txt")
39+
40+
with open(student_output_match_path, "r") as student_file:
41+
lines = [line.strip() for line in student_file.readlines()]
42+
43+
if len(lines) < 2:
44+
raise RuntimeError("❌ Student name and match not found in match.txt file")
45+
46+
student_name = lines[0]
47+
student_match = lines[1]
48+
49+
if student_name == "STUDENT TODO":
50+
raise RuntimeError("❌ You must replace kYourName in main.cpp with your name!")
51+
52+
student_initials = get_initials(student_name)
53+
if not student_initials:
54+
raise RuntimeError(f"❌ Invalid student name format: {student_name}")
55+
56+
expected_matches = {
57+
name for name in all_students if get_initials(name) == student_initials
58+
}
59+
60+
match = student_match.split("Your match is: ")[1].strip()
61+
62+
if match != "NO MATCHES FOUND.":
63+
if match not in expected_matches:
64+
raise RuntimeError(
65+
f"Matched student '{match}' is not in the expected set of matches: {expected_matches}"
66+
)
67+
print(f"✅ Matched student '{match}'")
68+
69+
70+
if __name__ == "__main__":
71+
grader = Autograder()
72+
grader.add_part("test_applicants_set", test_applicants_set)
73+
grader.add_part("test_match", test_match)
74+
75+
grader.setup = None
76+
grader.teardown = None
77+
grader.run()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
colorama==0.4.6

assignment2/autograder/student_output/match.txt

Whitespace-only changes.

assignment2/autograder/student_output/set.txt

Whitespace-only changes.

assignment2/autograder/utils.hpp

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
#include <fstream>
2+
#include <iostream>
3+
#include <sstream>
4+
#include <string>
5+
6+
int
7+
run_autograder()
8+
{
9+
auto run_program = [](std::string program,
10+
std::initializer_list<std::string> args,
11+
bool silent = false) {
12+
std::stringstream ss;
13+
14+
ss << program;
15+
for (const auto& arg : args) {
16+
ss << ' ' << arg;
17+
}
18+
19+
if (silent) {
20+
#ifdef _WIN32
21+
ss << " >nul 2>&1";
22+
#else
23+
ss << " >/dev/null 2>&1";
24+
#endif
25+
}
26+
27+
std::cout.flush();
28+
return system(ss.str().c_str());
29+
};
30+
31+
std::string python;
32+
for (const auto& option :
33+
{ "python", "python3", "/usr/bin/python3", "/usr/bin/python" }) {
34+
if (run_program(option, { "--version" }, true) == 0) {
35+
python = option;
36+
break;
37+
}
38+
}
39+
40+
if (python.empty()) {
41+
std::cerr
42+
<< "Python was not found on your system. Please install Python and "
43+
"try again."
44+
<< "\n";
45+
std::exit(1);
46+
}
47+
48+
/* #### Assignment Specific Operations #### */
49+
auto allMatches = get_applicants("students.txt");
50+
auto studentMatches = find_matches(kYourName, allMatches);
51+
auto match = get_match(studentMatches);
52+
53+
std::fstream matchFile("autograder/student_output/match.txt");
54+
std::fstream setFile("autograder/student_output/set.txt");
55+
56+
matchFile << kYourName << '\n' << "Your match is: " << match << '\n';
57+
for (const auto& student : allMatches) {
58+
setFile << student << '\n';
59+
}
60+
61+
// Flush streams so that the Python autograder is guaranteed to see their
62+
// changes
63+
matchFile.flush();
64+
setFile.flush();
65+
/* #### End of Assignment Specific Operations #### */
66+
67+
return run_program(python, { "autograder/autograder.py" });
68+
}
69+
70+
int
71+
main()
72+
{
73+
return run_autograder();
74+
}

0 commit comments

Comments
 (0)