From f41914efa99370ce4e0023a629db642198ce0bf2 Mon Sep 17 00:00:00 2001 From: Dan Cojocaru Date: Mon, 23 May 2022 01:00:49 +0300 Subject: [PATCH] =?UTF-8?q?Solved=20M=C4=83rire?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Marire/README.md | 21 ++++ Marire/marire.cpp | 287 ++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + 3 files changed, 309 insertions(+) create mode 100644 Marire/README.md create mode 100644 Marire/marire.cpp diff --git a/Marire/README.md b/Marire/README.md new file mode 100644 index 0000000..015b0c9 --- /dev/null +++ b/Marire/README.md @@ -0,0 +1,21 @@ +# CCIoT + +## Mărire + +### Problem + +A menu is created through which: + +1. Create a list of students identified by (name, year, 10 courses and 10 grades for each student, and the average corresponding to each student). +2. The list of students with all the data corresponding to each student is displayed. +3. Calculate the general average of each student (display name and average). +4. Students are displayed in descending order of average. Students with the same average are sorted alphabetically (display name + average + year). +5. All students from year 3 are displayed who have an average over 8.00 (name + year + average). +6. Insert a student's data (read from the keyboard) after the k-th(position in the list) student. If there are no k students it will be inserted at the beginning +or at the end of the list (user choice). +7. Remove all non-promoted students (average below 5.00) from the list. +8. Exit + +### Solution + +See [marire.cpp](./marire.cpp). diff --git a/Marire/marire.cpp b/Marire/marire.cpp new file mode 100644 index 0000000..ae31055 --- /dev/null +++ b/Marire/marire.cpp @@ -0,0 +1,287 @@ +#include // std::cin, std::cout +#include // std::setw, std::fixed, std::setprecision +#include // std::string +#include // std::vector +#include // std::pair +#include // std::accumulate +#include // std::sort +#include // std::array +#include // std::rand, std::srand +#include // std::time + +using std::cin; +using std::cout; +using std::endl; + +class Student { +private: + std::string _name; + int _year; + std::vector> _course_grades; + +public: + std::string get_name() const { return _name; } + void set_name(const std::string &new_name) { _name = new_name; } + int get_year() const { return _year; } + void set_year(int new_year) { _year = new_year; } + const std::vector>& get_course_grades() const { return _course_grades; } + void set_course_grades(const std::vector> new_course_grades) { _course_grades = new_course_grades; } + void add_course_grade(const std::string& course_name, double grade) { + _course_grades.emplace_back(course_name, grade); + } + + double get_average() const { + return std::accumulate( + _course_grades.begin(), + _course_grades.end(), + 0.0, + [](double acc, const std::pair &next){ + return acc + next.second; + } + ) / _course_grades.size(); + } +}; + +// for pretty printing: +int max_student_name = 12; + +void list_students(const std::vector& students) { + cout << "Listing " << students.size() << " student" << (students.size() == 1 ? "" : "s") << endl; + int index = 1; + for (const auto &student : students) { + cout << index << ". " << student.get_name() << " (year " << student.get_year() << "):" << endl; + for (const auto& course : student.get_course_grades()) { + cout << " " << course.first << " - " << std::fixed << std::setprecision(2) << course.second << endl; + } + + index++; + } +} + +void list_averages(const std::vector& students) { + cout << std::setw(max_student_name) << "Student Name" << " | " << "Average" << endl; + for (const auto& student: students) { + cout << std::setw(max_student_name) << student.get_name() << " | " << std::fixed << std::setprecision(2) << student.get_average() << endl; + } +} + +void list_sorted(std::vector students) { + std::sort( + students.begin(), + students.end(), + [](const Student &s1, const Student &s2) { + const auto s1_avg = s1.get_average(); + const auto s2_avg = s2.get_average(); + if (s1_avg != s2_avg) { + return s1_avg > s2_avg; + } + else { + return s1.get_name() < s2.get_name(); + } + } + ); + cout << std::setw(max_student_name) << "Student Name" << " | Average | Year" << endl; + for (const auto& student: students) { + cout + << std::setw(max_student_name) << student.get_name() + << " | " + << std::setw(7) << std::fixed << std::setprecision(2) << student.get_average() + << " | " + << student.get_year() + << endl; + } +} + +void list_year3_agt8(const std::vector& students) { + cout << "Students from year 3 with average over 8:" << endl; + cout << std::setw(max_student_name) << "Student Name" << " | Year | Average" << endl; + for (const auto& student: students) { + if (student.get_year() == 3 && student.get_average() > 8) { + cout + << std::setw(max_student_name) << student.get_name() + << " | " + << std::setw(4) << student.get_year() + << " | " + << std::fixed << std::setprecision(2) << student.get_average() + << endl; + } + } +} + +void insert_student(std::vector& students) { + std::string name; + int year; + std::vector> courses_grades; + + cout << "Name? "; + do { + std::getline(cin, name); + } while (name.length() == 0); + cout << "Year? "; + cin >> year; + // Workaround for newline stuck in buffer + std::string tmp; + std::getline(cin, tmp); + while (true) { + std::string course_name; + double grade; + + cout << "Course name? (Enter without typing to stop) "; + std::getline(cin, course_name); + if (course_name.length() == 0) { + break; + } + cout << "Grade? "; + cin >> grade; + // Workaround for newline stuck in buffer + std::getline(cin, tmp); + courses_grades.emplace_back(course_name, grade); + } + cout << "Added student." << endl; + + Student new_student; + new_student.set_name(name); + if (new_student.get_name().length() > max_student_name) { + max_student_name = new_student.get_name().length(); + } + new_student.set_year(year); + new_student.set_course_grades(courses_grades); + students.push_back(new_student); +} + +int remove_alt5(std::vector& students) { + std::vector indeces_to_remove; + for (int i = students.size() - 1; i >= 0; i--) { + if (students[i].get_average() < 5) { + indeces_to_remove.push_back(i); + } + } + for (auto i : indeces_to_remove) { + students.erase(students.begin() + i); + } + return indeces_to_remove.size(); +} + +std::array mock_names = { + "Elena", + "Mircea", + "Cornel", + "Ion", + "Nicolae", + "Mihai", + "Lavinia", + "Nicoleta", + "Ana", + "Denisa", + "Diana", + "Gheorghe", + "Darius", + "Sorin", + "Dragos", + "Stefan", + "Ioan", + "Viorel", + "Virgil", + "Octavian", + "Alina" +}; + +std::array mock_courses = { + "Maths", + "IT", + "C++", + "Java", + "Networking", + "Design", + "Class 7", + "Class 8", + "Class 9", + "Class 10", + "Class 11", + "Class 12", + "Class 13", + "Class 14", + "Class 15", + "Class 16", + "Class 17", + "Class 18", + "Class 19", + "Class 20", +}; + +void fill_with_mock_data(std::vector& students) { + // insert between 5 and 9 mock students + int count = 5 + (std::rand() % 5); + for (int i = 0; i < count; i++) { + int name_idx = std::rand() % mock_names.size(); + Student new_student; + new_student.set_name(mock_names[name_idx]); + if (new_student.get_name().length() > max_student_name) { + max_student_name = new_student.get_name().length(); + } + new_student.set_year(1 + std::rand() % 3); + + for (int j = 0; j < 10; j++) { + int course_idx = std::rand() % mock_courses.size(); + new_student.add_course_grade(mock_courses[course_idx], (2 + (std::rand() % 19)) / 2.0); + } + + students.push_back(new_student); + } +} + +int main() { + // seed rand + std::srand(std::time(nullptr)); + + std::vector students; + fill_with_mock_data(students); + + int choice; + + while (true) { + cout << "1. List students" << endl; + cout << "2. List averages" << endl; + cout << "3. Display sorted by averages" << endl; + cout << "4. Display students from year 3 with average > 8.0" << endl; + cout << "5. Insert student data" << endl; + cout << "6. Remove non-promoted students" << endl; + cout << "0. Exit" << endl; + + if (!(cin >> choice)) { + // Stop on end of input (Ctrl+D on Linux) + break; + } + + bool exit{false}; + switch (choice) { + case 0: + exit = true; + break; + case 1: + list_students(students); + break; + case 2: + list_averages(students); + break; + case 3: + list_sorted(students); + break; + case 4: + // list year 3 with average greater than 8 + list_year3_agt8(students); + break; + case 5: + insert_student(students); + break; + case 6: + // remove average less than 5 + int removed = remove_alt5(students); + cout << "Removed " << removed << " student" << (removed == 1 ? "" : "s") << endl; + break; + } + if (exit) { + break; + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index 99fe4c0..51f437b 100644 --- a/README.md +++ b/README.md @@ -3,3 +3,4 @@ - [Lab1](./Lab1/) - [Lab2](./Lab2/) - [Lab3](./Lab3/) +- [Mărire](./Marire/)