-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProjectTwo.cpp
More file actions
236 lines (214 loc) · 6.98 KB
/
Copy pathProjectTwo.cpp
File metadata and controls
236 lines (214 loc) · 6.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
// ProjectTwo.cpp
// Advising Assistance Program for ABCU Computer Science Department
// Author: Joshua Torres
// Date: June 2025
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <limits>
using namespace std;
// Represents a single course with its number, title, and prerequisites
struct Course {
string number;
string title;
vector<string> prerequisites;
};
// Alias for catalog data structure (balanced BST)
typedef map<string, Course> CourseCatalog;
// Displays the main menu options to the user
void displayMenu() {
cout << "\nWelcome to the course planner.\n"
<< "1. Load Data Structure.\n"
<< "2. Print Course List (Alphanumeric).\n"
<< "3. Print Course.\n"
<< "4. Print Course List (Topological Order).\n"
<< "9. Exit\n"
<< "What would you like to do? ";
}
// Loads course data from a CSV file into a map keyed by course number
CourseCatalog loadData(const string& inputName) {
CourseCatalog catalog;
string filename = inputName;
// Attempt to open the file as given
ifstream fin(filename);
if (!fin && filename.find('.') == string::npos) {
// If no extension is present, try adding ".csv"
fin.clear();
filename += ".csv";
fin.open(filename);
if (fin) {
cout << "Note: opened '" << filename << "' instead." << endl;
}
}
if (!fin) {
cerr << "Error: cannot open file '" << inputName << "'." << endl;
return catalog;
}
string line;
while (getline(fin, line)) {
if (line.empty()) continue; // Skip blank lines
stringstream ss(line);
Course c;
getline(ss, c.number, ',');
getline(ss, c.title, ',');
if (c.number.empty() || c.title.empty()) continue; // Skip invalid lines
string pre;
while (getline(ss, pre, ',')) {
if (!pre.empty()) { // Skip empty prerequisites
c.prerequisites.push_back(pre);
}
}
catalog[c.number] = c;
}
return catalog;
}
// Prints all courses in alphanumeric order
void printCourseList(const CourseCatalog& catalog) {
if (catalog.empty()) {
cout << "No data loaded. Use option 1 first." << endl;
return;
}
cout << "\nCourse List (Alphanumeric):" << endl;
for (const auto& [num, course] : catalog) {
cout << num << ", " << course.title << endl;
}
}
// Prints details for a specific course, including its prerequisites
void printCourseDetails(const CourseCatalog& catalog, const string& key) {
auto it = catalog.find(key);
if (it == catalog.end()) {
cout << "Course '" << key << "' not found." << endl;
return;
}
const Course& c = it->second;
cout << c.number << ", " << c.title << "\nPrerequisites: ";
if (c.prerequisites.empty()) {
cout << "None" << endl;
return;
}
for (size_t i = 0; i < c.prerequisites.size(); ++i) {
const string& pnum = c.prerequisites[i];
auto pit = catalog.find(pnum);
if (pit != catalog.end())
cout << pit->second.number << " (" << pit->second.title << ")";
else
cout << pnum << " (not found)";
if (i + 1 < c.prerequisites.size())
cout << ", ";
}
cout << endl;
}
// Prints all courses in a valid topological order using Kahn's algorithm
void printTopoOrder(const CourseCatalog& catalog) {
if (catalog.empty()) {
cout << "No data loaded. Use option 1 first." << endl;
return;
}
map<string, int> indegree; // Tracks in-degrees of courses
map<string, vector<string>> adj; // Adjacency list for prerequisites
// Initialize in-degree map and adjacency list
for (const auto& [num, course] : catalog) {
indegree[num] = 0;
}
for (const auto& [num, course] : catalog) {
for (const auto& pre : course.prerequisites) {
if (!catalog.count(pre)) { // Ensure prerequisite exists in the catalog
cerr << "Error: Prerequisite '" << pre << "' not found in catalog." << endl;
continue;
}
adj[pre].push_back(num);
indegree[num]++;
}
}
// Debugging: Print adjacency list and in-degrees
cout << "Adjacency List:\n";
for (const auto& [key, val] : adj) {
cout << key << ": ";
for (const auto& v : val) {
cout << v << " ";
}
cout << endl;
}
cout << "In-Degrees:\n";
for (const auto& [key, val] : indegree) {
cout << key << ": " << val << endl;
}
queue<string> q; // Queue for courses with zero in-degree
for (const auto& [num, deg] : indegree) {
if (deg == 0) {
q.push(num);
}
}
vector<string> topo; // Stores topological order
while (!q.empty()) {
string curr = q.front();
q.pop();
topo.push_back(curr);
for (const auto& nb : adj[curr]) {
if (--indegree[nb] == 0) {
q.push(nb);
}
}
}
// Check for cycles
if (topo.size() != catalog.size()) {
cout << "Cannot generate schedule: prerequisite cycle detected." << endl;
return;
}
// Print topological order
cout << "\nCourse List (Topological Order):" << endl;
for (const auto& num : topo) {
cout << num << ", " << catalog.at(num).title << endl;
}
}
int main() {
CourseCatalog catalog; // Stores course data
while (true) {
displayMenu(); // Show menu options
int choice;
if (!(cin >> choice)) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input. Please enter a number." << endl;
continue;
}
if (choice == 9) {
cout << "Thank you for using the course planner!" << endl;
break;
}
switch (choice) {
case 1: {
cout << "Enter the data filename (e.g., ABCU Advising Program Input.csv): ";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
string fname;
getline(cin, fname);
catalog = loadData(fname);
if (!catalog.empty())
cout << "Data loaded successfully." << endl;
break;
}
case 2:
printCourseList(catalog);
break;
case 3: {
cout << "What course do you want to know about? ";
string key;
cin >> key;
for (auto& ch : key)
ch = toupper(ch); // Convert to uppercase for uniformity
printCourseDetails(catalog, key);
break;
}
case 4:
printTopoOrder(catalog);
break;
default:
cout << choice << " is not a valid option." << endl;
}
}
return 0;
}