diff --git a/exercises/practice/grade-school/.meta/example.cpp b/exercises/practice/grade-school/.meta/example.cpp index 7514f189..b61bdf63 100644 --- a/exercises/practice/grade-school/.meta/example.cpp +++ b/exercises/practice/grade-school/.meta/example.cpp @@ -2,19 +2,24 @@ #include "grade_school.h" -using namespace std; - namespace grade_school { -void school::add(string const& name, int grade) { - vector& grade_roster = roster_[grade]; - auto it = lower_bound(grade_roster.begin(), grade_roster.end(), name); +void school::add(std::string const& name, int grade) { + if (students.find(name) != students.end()) { + return; + } + + students.insert(name); + + std::vector& grade_roster = students_by_grade[grade]; + auto it = std::lower_bound(grade_roster.begin(), grade_roster.end(), name); grade_roster.insert(it, name); } -vector school::grade(int grade) const { - auto it = roster_.find(grade); - return (it != roster_.end()) ? it->second : vector{}; +std::vector school::grade(int grade) const { + auto it = students_by_grade.find(grade); + return (it != students_by_grade.end()) ? it->second + : std::vector{}; } } // namespace grade_school diff --git a/exercises/practice/grade-school/.meta/example.h b/exercises/practice/grade-school/.meta/example.h index affad18d..d5c086be 100644 --- a/exercises/practice/grade-school/.meta/example.h +++ b/exercises/practice/grade-school/.meta/example.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -9,7 +10,7 @@ namespace grade_school { class school { public: const std::map>& roster() const { - return roster_; + return students_by_grade; } void add(std::string const& name, int grade); @@ -17,7 +18,8 @@ class school { std::vector grade(int grade) const; private: - std::map> roster_; + std::map> students_by_grade; + std::set students; }; } // namespace grade_school diff --git a/exercises/practice/grade-school/.meta/tests.toml b/exercises/practice/grade-school/.meta/tests.toml index eada129d..fd7eb1f5 100644 --- a/exercises/practice/grade-school/.meta/tests.toml +++ b/exercises/practice/grade-school/.meta/tests.toml @@ -1,24 +1,96 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. +# This is an auto-generated file. +# +# Regenerating this file via `configlet sync` will: +# - Recreate every `description` key/value pair +# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications +# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion) +# - Preserve any other key/value pair +# +# As user-added comments (using the # character) will be removed when this file +# is regenerated, comments can be added via a `comment` key. + +[a3f0fb58-f240-4723-8ddc-e644666b85cc] +description = "Roster is empty when no student is added" + +[9337267f-7793-4b90-9b4a-8e3978408824] +description = "Add a student" +include = false +reimplements = "6d0a30e4-1b4e-472e-8e20-c41702125667" [6d0a30e4-1b4e-472e-8e20-c41702125667] -description = "Adding a student adds them to the sorted roster" +description = "Student is added to the roster" + +[73c3ca75-0c16-40d7-82f5-ed8fe17a8e4a] +description = "Adding multiple students in the same grade in the roster" +include = false +reimplements = "233be705-dd58-4968-889d-fb3c7954c9cc" [233be705-dd58-4968-889d-fb3c7954c9cc] -description = "Adding more student adds them to the sorted roster" +description = "Multiple students in the same grade are added to the roster" + +[87c871c1-6bde-4413-9c44-73d59a259d83] +description = "Cannot add student to same grade in the roster more than once" +include = false +reimplements = "2bfc697c-adf2-4b65-8d0f-c46e085f796e" + +[c125dab7-2a53-492f-a99a-56ad511940d8] +description = "A student can't be in two different grades" +include = false + +[a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1] +description = "A student can only be added to the same grade in the roster once" +include = false +reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8" + +[d7982c4f-1602-49f6-a651-620f2614243a] +description = "Student not added to same grade in the roster more than once" +reimplements = "a0c7b9b8-0e89-47f8-8b4a-c50f885e79d1" + +[e70d5d8f-43a9-41fd-94a4-1ea0fa338056] +description = "Adding students in multiple grades" +include = false +reimplements = "75a51579-d1d7-407c-a2f8-2166e984e8ab" [75a51579-d1d7-407c-a2f8-2166e984e8ab] -description = "Adding students to different grades adds them to the same sorted roster" +description = "Students in multiple grades are added to the roster" -[a3f0fb58-f240-4723-8ddc-e644666b85cc] -description = "Roster returns an empty list if there are no students enrolled" +[7df542f1-57ce-433c-b249-ff77028ec479] +description = "Cannot add same student to multiple grades in the roster" +include = false +reimplements = "66c8e141-68ab-4a04-a15a-c28bc07fe6b9" -[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6] -description = "Student names with grades are displayed in the same sorted roster" +[6a03b61e-1211-4783-a3cc-fc7f773fba3f] +description = "A student cannot be added to more than one grade in the sorted roster" +include = false +reimplements = "c125dab7-2a53-492f-a99a-56ad511940d8" -[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e] -description = "Grade returns the students in that grade in alphabetical order" +[c7ec1c5e-9ab7-4d3b-be5c-29f2f7a237c5] +description = "Student not added to multiple grades in the roster" +reimplements = "6a03b61e-1211-4783-a3cc-fc7f773fba3f" + +[d9af4f19-1ba1-48e7-94d0-dabda4e5aba6] +description = "Students are sorted by grades in the roster" + +[d9fb5bea-f5aa-4524-9d61-c158d8906807] +description = "Students are sorted by name in the roster" + +[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6] +description = "Students are sorted by grades and then by name in the roster" [5e67aa3c-a3c6-4407-a183-d8fe59cd1630] -description = "Grade returns an empty list if there are no students in that grade" +description = "Grade is empty if no students in the roster" + +[1e0cf06b-26e0-4526-af2d-a2e2df6a51d6] +description = "Grade is empty if no students in that grade" + +[2bfc697c-adf2-4b65-8d0f-c46e085f796e] +description = "Student not added to same grade more than once" + +[66c8e141-68ab-4a04-a15a-c28bc07fe6b9] +description = "Student not added to multiple grades" + +[c9c1fc2f-42e0-4d2c-b361-99271f03eda7] +description = "Student not added to other grade for multiple grades" + +[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e] +description = "Students are sorted by name in a grade" diff --git a/exercises/practice/grade-school/grade_school_test.cpp b/exercises/practice/grade-school/grade_school_test.cpp index 74c5547d..8b502004 100644 --- a/exercises/practice/grade-school/grade_school_test.cpp +++ b/exercises/practice/grade-school/grade_school_test.cpp @@ -1,6 +1,8 @@ #include "grade_school.h" #include +#include +#include #ifdef EXERCISM_TEST_SUITE #include #else @@ -9,83 +11,173 @@ using namespace std; -TEST_CASE("a_new_school_has_an_empty_roster") { - const grade_school::school school_{}; - REQUIRE(school_.roster().empty()); +TEST_CASE("roster_is_empty_when_no_student_is_added", + "[a3f0fb58-f240-4723-8ddc-e644666b85cc]") { + const grade_school::school school{}; + + REQUIRE(school.roster().empty()); } #if defined(EXERCISM_RUN_ALL_TESTS) -TEST_CASE("adding_a_student_adds_them_to_the_roster_for_the_given_grade") { - grade_school::school school_; - school_.add("Aimee", 2); - - const auto actual = school_.roster(); +TEST_CASE("student_is_added_to_the_roster", + "[6d0a30e4-1b4e-472e-8e20-c41702125667]") { + grade_school::school school; + school.add("Aimee", 2); const map> expected{{2, {"Aimee"}}}; - REQUIRE(expected == actual); + REQUIRE(expected == school.roster()); } -TEST_CASE("adding_more_students_to_the_same_grade_adds_them_to_the_roster") { - grade_school::school school_; - school_.add("Blair", 2); - school_.add("James", 2); - school_.add("Paul", 2); - - const auto actual = school_.roster(); +TEST_CASE("multiple_students_in_the_same_grade_are_added_to_the_roster", + "[233be705-dd58-4968-889d-fb3c7954c9cc]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("Paul", 2); const map> expected{{2, {"Blair", "James", "Paul"}}}; - REQUIRE(expected == actual); + REQUIRE(expected == school.roster()); } -TEST_CASE("adding_students_to_different_grades_adds_them_to_the_roster") { - grade_school::school school_; - school_.add("Chelsea", 3); - school_.add("Logan", 7); +TEST_CASE("student_not_added_to_same_grade_in_the_roster_more_than_once", + "[d7982c4f-1602-49f6-a651-620f2614243a]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("James", 2); + school.add("Paul", 2); - const auto actual = school_.roster(); + const map> expected{{2, {"Blair", "James", "Paul"}}}; + REQUIRE(expected == school.roster()); +} + +TEST_CASE("students_in_multiple_grades_are_added_to_the_roster", + "[75a51579-d1d7-407c-a2f8-2166e984e8ab]") { + grade_school::school school; + school.add("Chelsea", 3); + school.add("Logan", 7); const map> expected{{3, {"Chelsea"}}, {7, {"Logan"}}}; - REQUIRE(expected == actual); + REQUIRE(expected == school.roster()); } -TEST_CASE("grade_returns_the_students_in_that_grade_in_alphabetical_order") { - grade_school::school school_; - school_.add("Franklin", 5); - school_.add("Bradley", 5); - school_.add("Jeff", 1); +TEST_CASE("student_not_added_to_multiple_grades_in_the_roster", + "[c7ec1c5e-9ab7-4d3b-be5c-29f2f7a237c5]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("James", 3); + school.add("Paul", 3); + + const map> expected{{2, {"Blair", "James"}}, + {3, {"Paul"}}}; + REQUIRE(expected == school.roster()); +} - const auto actual = school_.grade(5); +TEST_CASE("students_are_sorted_by_grades_in_the_roster", + "[d9af4f19-1ba1-48e7-94d0-dabda4e5aba6]") { + grade_school::school school; + school.add("Jim", 3); + school.add("Peter", 2); + school.add("Anna", 1); - const vector expected{"Bradley", "Franklin"}; - REQUIRE(expected == actual); + const map> expected{ + {1, {"Anna"}}, {2, {"Peter"}}, {3, {"Jim"}}}; + REQUIRE(expected == school.roster()); } -TEST_CASE( - "grade_returns_an_empty_array_if_there_are_no_students_in_that_grade") { - const grade_school::school school_{}; - const auto actual = school_.grade(1); +TEST_CASE("students_are_sorted_by_name_in_the_roster", + "[d9fb5bea-f5aa-4524-9d61-c158d8906807]") { + grade_school::school school; + school.add("Peter", 2); + school.add("Zoe", 2); + school.add("Alex", 2); - REQUIRE(actual.empty()); + const map> expected{{2, {"Alex", "Peter", "Zoe"}}}; + REQUIRE(expected == school.roster()); } -TEST_CASE("the_student_names_in_each_grade_in_the_roster_are_sorted") { - grade_school::school school_; - school_.add("Jennifer", 4); - school_.add("Kareem", 6); - school_.add("Christopher", 4); - school_.add("Kyle", 3); +TEST_CASE("students_are_sorted_by_grades_and_then_by_name_in_the_roster", + "[180a8ff9-5b94-43fc-9db1-d46b4a8c93b6]") { + grade_school::school school; + school.add("Peter", 2); + school.add("Anna", 1); + school.add("Barb", 1); + school.add("Zoe", 2); + school.add("Alex", 2); + school.add("Jim", 3); + school.add("Charlie", 1); + + const map> expected{{1, {"Anna", "Barb", "Charlie"}}, + {2, {"Alex", "Peter", "Zoe"}}, + {3, {"Jim"}}}; + REQUIRE(expected == school.roster()); +} - const auto actual = school_.roster(); +TEST_CASE("grade_is_empty_if_no_students_in_the_roster", + "[5e67aa3c-a3c6-4407-a183-d8fe59cd1630]") { + const grade_school::school school{}; - const map> expected{ - {3, {"Kyle"}}, {4, {"Christopher", "Jennifer"}}, {6, {"Kareem"}}}; - REQUIRE(expected == actual); + REQUIRE(school.grade(1).empty()); } -TEST_CASE("checking_a_grade_should_not_change_the_roster") { - const grade_school::school school_{}; - school_.grade(1); - REQUIRE(school_.roster().empty()); +TEST_CASE("grade_is_empty_if_no_students_in_that_grade", + "[1e0cf06b-26e0-4526-af2d-a2e2df6a51d6]") { + grade_school::school school; + school.add("Peter", 2); + school.add("Zoe", 2); + school.add("Alex", 2); + school.add("Jim", 3); + + const vector expected{}; + REQUIRE(expected == school.grade(1)); +} + +TEST_CASE("student_not_added_to_same_grade_more_than_once", + "[2bfc697c-adf2-4b65-8d0f-c46e085f796e]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("James", 2); + school.add("Paul", 2); + + const vector expected{"Blair", "James", "Paul"}; + REQUIRE(expected == school.grade(2)); +} + +TEST_CASE("student_not_added_to_multiple_grades", + "[66c8e141-68ab-4a04-a15a-c28bc07fe6b9]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("James", 3); + school.add("Paul", 3); + + const vector expected{"Blair", "James"}; + REQUIRE(expected == school.grade(2)); +} + +TEST_CASE("student_not_added_to_other_grade_for_multiple_grades", + "[c9c1fc2f-42e0-4d2c-b361-99271f03eda7]") { + grade_school::school school; + school.add("Blair", 2); + school.add("James", 2); + school.add("James", 3); + school.add("Paul", 3); + + const vector expected{"Paul"}; + REQUIRE(expected == school.grade(3)); +} + +TEST_CASE("students_are_sorted_by_name_in_a_grade", + "[1bfbcef1-e4a3-49e8-8d22-f6f9f386187e]") { + grade_school::school school; + school.add("Franklin", 5); + school.add("Bradley", 5); + school.add("Jeff", 1); + + const vector expected{"Bradley", "Franklin"}; + REQUIRE(expected == school.grade(5)); } #endif