Skip to content

Commit 3ffe4b7

Browse files
authored
fix(anagram): allow arbitrary container in solution (#933)
1 parent 66c8cdc commit 3ffe4b7

File tree

1 file changed

+82
-74
lines changed

1 file changed

+82
-74
lines changed

exercises/practice/anagram/anagram_test.cpp

+82-74
Original file line numberDiff line numberDiff line change
@@ -5,160 +5,168 @@
55
#include "test/catch.hpp"
66
#endif
77

8+
#include <string>
9+
#include <unordered_set>
10+
811
using namespace std;
912

1013
// Anagram exercise test case data version 1.5.0
1114

12-
TEST_CASE("no_matches")
13-
{
15+
// This class is a helper to allow the solution to return any container type. It
16+
// takes an std::unordered_set of expected values and provides a method
17+
// `is_identical_to` that checks if a given container is as expected. Since the
18+
// method is a method template, it works for any container.
19+
class ExpectedSet {
20+
public:
21+
explicit ExpectedSet(std::unordered_set<std::string> e)
22+
: expected{std::move(e)} {}
23+
24+
template <typename Container>
25+
bool is_identical_to(Container const& container) {
26+
return std::size(expected) == std::size(container) &&
27+
std::all_of(std::cbegin(container), std::cend(container),
28+
[this](auto const& elem) {
29+
return expected.count(elem) == 1;
30+
});
31+
}
32+
33+
private:
34+
std::unordered_set<std::string> expected{};
35+
};
36+
37+
TEST_CASE("no_matches") {
1438
// 'anagram::anagram' defines a class
1539
anagram::anagram subject = anagram::anagram("diaper");
1640
auto matches = subject.matches({"hello", "world", "zombies", "pants"});
17-
vector<string> expected;
18-
19-
REQUIRE(expected == matches);
41+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
2042
}
2143

2244
#if defined(EXERCISM_RUN_ALL_TESTS)
23-
TEST_CASE("detects_two_anagrams", "[findAnagrams][03eb9bbe-8906-4ea0-84fa-ffe711b52c8b]")
24-
{
45+
TEST_CASE("detects_two_anagrams",
46+
"[findAnagrams][03eb9bbe-8906-4ea0-84fa-ffe711b52c8b]") {
2547
auto subject = anagram::anagram("solemn");
26-
auto matches = subject.matches({"lemons", "cherry", "melons"});
27-
vector<string> expected{"lemons", "melons"};
48+
auto matches = subject.matches({"cherry", "melons", "lemons"});
2849

29-
REQUIRE(expected == matches);
50+
REQUIRE(ExpectedSet({"lemons", "melons"}).is_identical_to(matches));
3051
}
3152

32-
TEST_CASE("does_not_detect_anagram_subsets", "[findAnagrams][a27558ee-9ba0-4552-96b1-ecf665b06556]")
33-
{
53+
TEST_CASE("does_not_detect_anagram_subsets",
54+
"[findAnagrams][a27558ee-9ba0-4552-96b1-ecf665b06556]") {
3455
auto subject = anagram::anagram("good");
3556
auto matches = subject.matches({"dog", "goody"});
36-
vector<string> expected;
3757

38-
REQUIRE(expected == matches);
58+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
3959
}
4060

41-
TEST_CASE("detects_anagram", "[findAnagrams][64cd4584-fc15-4781-b633-3d814c4941a4]")
42-
{
61+
TEST_CASE("detects_anagram",
62+
"[findAnagrams][64cd4584-fc15-4781-b633-3d814c4941a4]") {
4363
auto subject = anagram::anagram("listen");
4464
auto matches = subject.matches({"enlists", "google", "inlets", "banana"});
45-
vector<string> expected{"inlets"};
4665

47-
REQUIRE(expected == matches);
66+
REQUIRE(ExpectedSet({"inlets"}).is_identical_to(matches));
4867
}
4968

50-
TEST_CASE("detects_three_anagrams", "[findAnagrams][99c91beb-838f-4ccd-b123-935139917283]")
51-
{
69+
TEST_CASE("detects_three_anagrams",
70+
"[findAnagrams][99c91beb-838f-4ccd-b123-935139917283]") {
5271
auto subject = anagram::anagram("allergy");
53-
auto matches = subject.matches({
54-
"gallery",
55-
"ballerina",
56-
"regally",
57-
"clergy",
58-
"largely",
59-
"leading"
60-
});
61-
vector<string> expected{"gallery", "regally", "largely"};
72+
auto matches = subject.matches(
73+
{"gallery", "ballerina", "regally", "clergy", "largely", "leading"});
6274

63-
REQUIRE(expected == matches);
75+
REQUIRE(ExpectedSet({"gallery", "regally", "largely"})
76+
.is_identical_to(matches));
6477
}
6578

66-
TEST_CASE("detects_multiple_anagrams_with_different_case", "[findAnagrams][78487770-e258-4e1f-a646-8ece10950d90]")
67-
{
79+
TEST_CASE("detects_multiple_anagrams_with_different_case",
80+
"[findAnagrams][78487770-e258-4e1f-a646-8ece10950d90]") {
6881
auto subject = anagram::anagram("nose");
6982
auto matches = subject.matches({"Eons", "ONES"});
70-
vector<string> expected{"Eons", "ONES"};
7183

72-
REQUIRE(expected == matches);
84+
REQUIRE(ExpectedSet({"Eons", "ONES"}).is_identical_to(matches));
7385
}
7486

75-
TEST_CASE("does_not_detect_non_anagrams_with_identical_checksum", "[findAnagrams][1d0ab8aa-362f-49b7-9902-3d0c668d557b]")
76-
{
87+
TEST_CASE("does_not_detect_non_anagrams_with_identical_checksum",
88+
"[findAnagrams][1d0ab8aa-362f-49b7-9902-3d0c668d557b]") {
7789
auto subject = anagram::anagram("mass");
7890
auto matches = subject.matches({"last"});
79-
vector<string> expected;
8091

81-
REQUIRE(expected == matches);
92+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
8293
}
8394

84-
TEST_CASE("detects_anagrams_case_insensitively", "[findAnagrams][9e632c0b-c0b1-4804-8cc1-e295dea6d8a8]")
85-
{
95+
TEST_CASE("detects_anagrams_case_insensitively",
96+
"[findAnagrams][9e632c0b-c0b1-4804-8cc1-e295dea6d8a8]") {
8697
auto subject = anagram::anagram("Orchestra");
8798
auto matches = subject.matches({"cashregister", "Carthorse", "radishes"});
88-
vector<string> expected{"Carthorse"};
8999

90-
REQUIRE(expected == matches);
100+
REQUIRE(ExpectedSet({"Carthorse"}).is_identical_to(matches));
91101
}
92102

93-
TEST_CASE("detects_anagrams_using_case_insensitive_subject", "[findAnagrams][b248e49f-0905-48d2-9c8d-bd02d8c3e392]")
94-
{
103+
TEST_CASE("detects_anagrams_using_case_insensitive_subject",
104+
"[findAnagrams][b248e49f-0905-48d2-9c8d-bd02d8c3e392]") {
95105
auto subject = anagram::anagram("Orchestra");
96106
auto matches = subject.matches({"cashregister", "carthorse", "radishes"});
97-
vector<string> expected{"carthorse"};
98107

99-
REQUIRE(expected == matches);
108+
REQUIRE(ExpectedSet({"carthorse"}).is_identical_to(matches));
100109
}
101110

102-
TEST_CASE("detects_anagrams_using_case_insensitive_possible_matches", "[findAnagrams][f367325c-78ec-411c-be76-e79047f4bd54]")
103-
{
111+
TEST_CASE("detects_anagrams_using_case_insensitive_possible_matches",
112+
"[findAnagrams][f367325c-78ec-411c-be76-e79047f4bd54]") {
104113
auto subject = anagram::anagram("orchestra");
105114
auto matches = subject.matches({"cashregister", "Carthorse", "radishes"});
106-
vector<string> expected{"Carthorse"};
107115

108-
REQUIRE(expected == matches);
116+
REQUIRE(ExpectedSet({"Carthorse"}).is_identical_to(matches));
109117
}
110118

111-
TEST_CASE("does_not_detect_an_anagram_if_the_original_word_is_repeated", "[findAnagrams][630abb71-a94e-4715-8395-179ec1df9f91]")
112-
{
119+
TEST_CASE("does_not_detect_an_anagram_if_the_original_word_is_repeated",
120+
"[findAnagrams][630abb71-a94e-4715-8395-179ec1df9f91]") {
113121
auto subject = anagram::anagram("go");
114122
auto matches = subject.matches({"goGoGO"});
115-
vector<string> expected;
116123

117-
REQUIRE(expected == matches);
124+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
118125
}
119126

120-
TEST_CASE("anagrams_must_use_all_letters_exactly_once", "[findAnagrams][9878a1c9-d6ea-4235-ae51-3ea2befd6842]")
121-
{
127+
TEST_CASE("anagrams_must_use_all_letters_exactly_once",
128+
"[findAnagrams][9878a1c9-d6ea-4235-ae51-3ea2befd6842]") {
122129
auto subject = anagram::anagram("tapper");
123130
auto matches = subject.matches({"patter"});
124-
vector<string> expected;
125131

126-
REQUIRE(expected == matches);
132+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
127133
}
128134

129-
TEST_CASE("words_are_not_anagrams_of_themselves", "[findAnagrams][68934ed0-010b-4ef9-857a-20c9012d1ebf]")
130-
{
135+
TEST_CASE("words_are_not_anagrams_of_themselves",
136+
"[findAnagrams][68934ed0-010b-4ef9-857a-20c9012d1ebf]") {
131137
auto subject = anagram::anagram("BANANA");
132138
auto matches = subject.matches({"BANANA"});
133-
vector<string> expected;
134139

135-
REQUIRE(expected == matches);
140+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
136141
}
137142

138-
TEST_CASE("words_are_not_anagrams_of_themselves_even_if_letter_case_is_partially_different", "[findAnagrams][589384f3-4c8a-4e7d-9edc-51c3e5f0c90e]")
139-
{
143+
TEST_CASE(
144+
// clang-format off
145+
"words_are_not_anagrams_of_themselves_even_if_letter_case_is_partially_different",
146+
// clang-format on
147+
"[findAnagrams][589384f3-4c8a-4e7d-9edc-51c3e5f0c90e]") {
140148
auto subject = anagram::anagram("BANANA");
141149
auto matches = subject.matches({"Banana"});
142-
vector<string> expected;
143150

144-
REQUIRE(expected == matches);
151+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
145152
}
146153

147-
TEST_CASE("words_are_not_anagrams_of_themselves_even_if_letter_case_is_completely_different", "[findAnagrams][ba53e423-7e02-41ee-9ae2-71f91e6d18e6]")
148-
{
154+
TEST_CASE(
155+
// clang-format off
156+
"words_are_not_anagrams_of_themselves_even_if_letter_case_is_completely_different",
157+
// clang-format on
158+
"[findAnagrams][ba53e423-7e02-41ee-9ae2-71f91e6d18e6]") {
149159
auto subject = anagram::anagram("BANANA");
150160
auto matches = subject.matches({"banana"});
151-
vector<string> expected;
152161

153-
REQUIRE(expected == matches);
162+
REQUIRE(ExpectedSet({}).is_identical_to(matches));
154163
}
155164

156-
TEST_CASE("words_other_than_themselves_can_be_anagrams", "[findAnagrams][33d3f67e-fbb9-49d3-a90e-0beb00861da7]")
157-
{
165+
TEST_CASE("words_other_than_themselves_can_be_anagrams",
166+
"[findAnagrams][33d3f67e-fbb9-49d3-a90e-0beb00861da7]") {
158167
auto subject = anagram::anagram("LISTEN");
159168
auto matches = subject.matches({"Silent", "LISTEN"});
160-
vector<string> expected{"Silent"};
161169

162-
REQUIRE(expected == matches);
170+
REQUIRE(ExpectedSet({"Silent"}).is_identical_to(matches));
163171
}
164172
#endif

0 commit comments

Comments
 (0)