Last active
January 7, 2016 05:12
-
-
Save mhamrah/79ed07a00209754a0ab1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if !defined(REQUIRE_EQUAL_CONTAINERS_H) | |
#define REQUIRE_EQUAL_CONTAINERS_H | |
#include <boost/version.hpp> | |
#include <utility> | |
#include <vector> | |
#if BOOST_VERSION >= 105900 | |
namespace boost | |
{ | |
namespace test_tools | |
{ | |
namespace tt_detail | |
{ | |
// teach Boost.Test how to print std::vector<T> | |
template <typename T> | |
inline std::ostream &operator<<(std::ostream &str, std::vector<T> const &items) | |
{ | |
str << '['; | |
bool first = true; | |
for (auto const& element : items) { | |
str << (!first ? "," : "") << element; | |
first = false; | |
} | |
return str << ']'; | |
} | |
// teach Boost.Test how to print std::pair<K,V> | |
template <typename K, typename V> | |
inline std::ostream &operator<<(std::ostream &str, std::pair<K, V> const& item) | |
{ | |
return str << '<' << item.first << ',' << item.second << '>'; | |
} | |
} // namespace tt_detail | |
} // namespace test_tools | |
} // namespace boost | |
#else // BOOST_VERSION < 105900 | |
namespace boost | |
{ | |
// teach Boost.Test how to print std::vector to wrap_stringstream | |
template <typename T> | |
inline wrap_stringstream& | |
operator<<(wrap_stringstream& wrapped, std::vector<T> const& item) | |
{ | |
wrapped << '['; | |
bool first = true; | |
for (auto const& element : item) { | |
wrapped << (!first ? "," : "") << element; | |
first = false; | |
} | |
return wrapped << ']'; | |
} | |
// teach Boost.Test how to print std::pair<K,V> to wrap_stringstream | |
template <typename K, typename V> | |
inline wrap_stringstream &operator<<(wrap_stringstream &str, std::pair<K, V> const& item) | |
{ | |
return str << '<' << item.first << ',' << item.second << '>'; | |
} | |
namespace test_tools | |
{ | |
// teach Boost.Test how to print std::pair with BOOST_REQUIRE_EQUAL | |
template<> | |
struct print_log_value<std::pair<int, int>> | |
{ | |
void operator()(std::ostream& ostr, std::pair<int, int> const& item) | |
{ | |
ostr << '<' << item.first << ',' << item.second << '>'; | |
} | |
}; | |
} // namespace test_tools | |
} // namespace boost | |
#endif // BOOST_VERSION | |
#define REQUIRE_EQUAL_CONTAINERS(left_, right_) \ | |
BOOST_REQUIRE_EQUAL_COLLECTIONS(left_.begin(), left_.end(), right_.begin(), right_.end()) | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#if !defined(WORD_COUNT_H) | |
#define WORD_COUNT_H | |
#include <map> | |
#include <string> | |
namespace word_count | |
{ | |
std::map<std::string, int> words(std::string const& text); | |
} | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "word_count.h" | |
#include <algorithm> | |
#include <cctype> | |
#include <iterator> | |
#include <vector> | |
#include <boost/algorithm/string.hpp> | |
using namespace std; | |
namespace | |
{ | |
string normalize_text(string const& text) | |
{ | |
string normalized; | |
transform(text.begin(), text.end(), back_inserter(normalized), | |
[](const char c) { return (isalnum(c) || c == '\'') ? tolower(c) : ' '; }); | |
return normalized; | |
} | |
string trim_word(string const& word) | |
{ | |
return boost::trim_copy_if(word, boost::is_any_of("' ")); | |
} | |
vector<string> split_text_into_words(string const& text) | |
{ | |
vector<string> words; | |
boost::split(words, text, boost::is_any_of("\t ")); | |
transform(words.begin(), words.end(), words.begin(), trim_word); | |
return words; | |
} | |
} | |
namespace word_count | |
{ | |
map<string, int> words(string const& text) | |
{ | |
map<string, int> count; | |
for (auto const& word : split_text_into_words(normalize_text(text))) | |
{ | |
if (!word.empty()) | |
{ | |
++count[word]; | |
} | |
} | |
return count; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "word_count.h" | |
#define BOOST_TEST_MAIN | |
#include <boost/test/unit_test.hpp> | |
#include <map> | |
#include "require_equal_containers.h" | |
using namespace std; | |
BOOST_AUTO_TEST_CASE(counts_one_word) | |
{ | |
const map<string, int> expected{{"word", 1}}; | |
const auto actual = word_count::words("word"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
#if defined(EXERCISM_RUN_ALL_TESTS) | |
BOOST_AUTO_TEST_CASE(counts_one_of_each) | |
{ | |
const map<string, int> expected{{"one", 1}, {"of", 1}, {"each", 1}}; | |
const auto actual = word_count::words("one of each"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(counts_multiple_occurrences) | |
{ | |
const map<string, int> expected{{"one", 1}, {"fish", 4}, {"two", 1}, {"red", 1}, {"blue", 1}}; | |
const auto actual = word_count::words("one fish two fish red fish blue fish"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(ignores_punctuation) | |
{ | |
const map<string, int> expected{{"car", 1}, {"carpet", 1}, {"as", 1}, {"java", 1}, {"javascript", 1}}; | |
const auto actual = word_count::words("car : carpet as java : javascript!!&@$%^&"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(includes_numbers) | |
{ | |
const map<string, int> expected{{"testing", 2}, {"1", 1}, {"2", 1}}; | |
const auto actual = word_count::words("testing, 1, 2 testing"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(normalizes_case) | |
{ | |
const map<string, int> expected{{"go", 3}}; | |
const auto actual = word_count::words("go Go GO"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(counts_constructor) | |
{ | |
const map<string, int> expected{{"constructor", 2}}; | |
const auto actual = word_count::words("constructor Constructor"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(counts_multiline) | |
{ | |
const map<string, int> expected{{"hello", 1}, {"world", 1}}; | |
const auto actual = word_count::words("hello\nworld"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(count_everything_just_once) | |
{ | |
const map<string, int> expected{{"all", 2}, {"the", 2}, {"kings", 2}, {"horses", 1}, {"and", 1}, {"men", 1}}; | |
const auto actual = word_count::words("all the kings horses and all the kings men"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(handles_cramped_list) | |
{ | |
const map<string, int> expected{{"one", 1}, {"two", 1}, {"three", 1}}; | |
const auto actual = word_count::words("one,two,three"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(with_apostrophes) | |
{ | |
const map<string, int> expected{{"first", 1}, {"don't", 2}, {"laugh", 1}, {"then", 1}, {"cry", 1}}; | |
const auto actual = word_count::words("First: don't laugh. Then: don't cry."); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(with_free_standing_apostrophes) | |
{ | |
const map<string, int> expected{{ "go", 3 }}; | |
const auto actual = word_count::words("go ' Go '' GO"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
BOOST_AUTO_TEST_CASE(with_apostrophes_as_quotes) | |
{ | |
const map<string, int> expected{{"she", 1}, {"said", 1}, {"let's", 1}, {"meet", 1}, {"at", 1}, {"twelve", 1}, {"o'clock", 1}}; | |
const auto actual = word_count::words("She said, 'let's meet at twelve o'clock'"); | |
REQUIRE_EQUAL_CONTAINERS(expected, actual); | |
} | |
#endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compile error: