diff --git a/CMakeLists.txt b/CMakeLists.txt index b3d20a8..c9067cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -62,7 +62,7 @@ include_directories(shared) ##### subdirectories ##### -set(DIRS week-W week-2 week-3 week-4 week-5 week-6 week-7 week-8 week-9 week-10 week-11) +set(DIRS week-W week-2 week-3 week-4 week-5 week-6 week-7 week-8 week-9 week-10 week-11 week-14) foreach(DIR ${DIRS}) add_subdirectory(${DIR}) endforeach() diff --git a/week-14/CMakeLists.txt b/week-14/CMakeLists.txt new file mode 100644 index 0000000..fd50429 --- /dev/null +++ b/week-14/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DIRS task-12-06 task-12-07 task-12-08) +foreach(DIR ${DIRS}) + add_subdirectory(${DIR}) +endforeach() diff --git a/week-14/task-12-06/CMakeLists.txt b/week-14/task-12-06/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-14/task-12-06/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-14/task-12-06/include/title_case.hpp b/week-14/task-12-06/include/title_case.hpp new file mode 100644 index 0000000..a165f98 --- /dev/null +++ b/week-14/task-12-06/include/title_case.hpp @@ -0,0 +1,18 @@ +#pragma once + +#include +#include +#include +#include + +namespace my_algorithms { + +void title_case(std::string& str) { + std::ranges::transform( + std::views::zip(str, std::views::iota(0)), str.begin(), [&](auto&& pair) { + auto [c, idx] = pair; + return (idx == 0 || std::isspace(str[idx - 1])) ? std::toupper(c) : std::tolower(c); + }); +} + +} // namespace my_algorithms diff --git a/week-14/task-12-06/test/CMakeLists.txt b/week-14/task-12-06/test/CMakeLists.txt new file mode 100644 index 0000000..82ae9c6 --- /dev/null +++ b/week-14/task-12-06/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-12-06.cpp) diff --git a/week-14/task-12-06/test/test-12-06.cpp b/week-14/task-12-06/test/test-12-06.cpp new file mode 100644 index 0000000..81c30b4 --- /dev/null +++ b/week-14/task-12-06/test/test-12-06.cpp @@ -0,0 +1,40 @@ +#include "gtest/gtest.h" +#include "title_case.hpp" + +using my_algorithms::title_case; + +TEST(TitleCaseTest, HandlesEmptyString) { + std::string str; + title_case(str); + EXPECT_EQ(str, ""); +} + +TEST(TitleCaseTest, HandlesSingleWord) { + std::string str = "hello"; + title_case(str); + EXPECT_EQ(str, "Hello"); +} + +TEST(TitleCaseTest, HandlesMultipleWords) { + std::string str = "heLLo, woRLD"; + title_case(str); + EXPECT_EQ(str, "Hello, World"); +} + +TEST(TitleCaseTest, HandlesLeadingAndTrailingSpaces) { + std::string str = " test CASE "; + title_case(str); + EXPECT_EQ(str, " Test Case "); +} + +TEST(TitleCaseTest, HandlesMixedCaseWithNumbers) { + std::string str = "1st plaCE"; + title_case(str); + EXPECT_EQ(str, "1st Place"); +} + +TEST(TitleCaseTest, HandlesAllUppercase) { + std::string str = "ALL UPPER"; + title_case(str); + EXPECT_EQ(str, "All Upper"); +} diff --git a/week-14/task-12-07/CMakeLists.txt b/week-14/task-12-07/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-14/task-12-07/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-14/task-12-07/include/join.hpp b/week-14/task-12-07/include/join.hpp new file mode 100644 index 0000000..1ee1fe0 --- /dev/null +++ b/week-14/task-12-07/include/join.hpp @@ -0,0 +1,20 @@ +#pragma once + +namespace my_algorithm { + +template + requires requires { + requires std::convertible_to, std::string_view>; + } +std::string join(const Range& strings, const std::string& delimiter) { + std::string res; + for (auto it = std::begin(strings); it != std::end(strings); ++it) { + if (it != std::begin(strings)) { + res += delimiter; + } + res += *it; + } + return res; +} + +} // namespace my_algorithm diff --git a/week-14/task-12-07/test/CMakeLists.txt b/week-14/task-12-07/test/CMakeLists.txt new file mode 100644 index 0000000..4257833 --- /dev/null +++ b/week-14/task-12-07/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-12-07.cpp) diff --git a/week-14/task-12-07/test/test-12-07.cpp b/week-14/task-12-07/test/test-12-07.cpp new file mode 100644 index 0000000..4e4402f --- /dev/null +++ b/week-14/task-12-07/test/test-12-07.cpp @@ -0,0 +1,37 @@ +#include +#include + +#include "gtest/gtest.h" +#include "join.hpp" + +using my_algorithm::join; + +TEST(JoinTest, HandlesEmptyRange) { + const std::vector empty_vec; + EXPECT_EQ(join(empty_vec, ","), ""); +} + +TEST(JoinTest, HandlesSingleString) { + const std::list single = {"hello"}; + EXPECT_EQ(join(single, " "), "hello"); +} + +TEST(JoinTest, JoinsMultipleStrings) { + const std::vector strings = {"a", "b", "c"}; + EXPECT_EQ(join(strings, ","), "a,b,c"); +} + +TEST(JoinTest, WorksWithStringView) { + const std::vector sv = {"x", "y", "z"}; + EXPECT_EQ(join(sv, "->"), "x->y->z"); +} + +TEST(JoinTest, HandlesMultiCharDelimiter) { + const std::vector strings = {"1", "2", "3"}; + EXPECT_EQ(join(strings, "###"), "1###2###3"); +} + +TEST(JoinTest, WorksWithNonOwningTypes) { + const char* cstrings[] = {"quick", "brown", "fox"}; + EXPECT_EQ(join(cstrings, "..."), "quick...brown...fox"); +} diff --git a/week-14/task-12-08/CMakeLists.txt b/week-14/task-12-08/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-14/task-12-08/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-14/task-12-08/include/tokenize.hpp b/week-14/task-12-08/include/tokenize.hpp new file mode 100644 index 0000000..4ba10d0 --- /dev/null +++ b/week-14/task-12-08/include/tokenize.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include + +namespace my_algorithm { + +std::vector tokenize(const std::string& str, + const std::unordered_set& delimiters) { + std::vector tokens; + auto start = str.begin(); + auto end = str.end(); + while (start != end) { + while (start != end && delimiters.contains(*start)) { + ++start; + } + auto token_end = start; + while (token_end != end && !delimiters.contains(*token_end)) { + ++token_end; + } + if (start != token_end) { + tokens.emplace_back(start, token_end); + } + start = token_end; + } + return tokens; +} + +} // namespace my_algorithm diff --git a/week-14/task-12-08/test/CMakeLists.txt b/week-14/task-12-08/test/CMakeLists.txt new file mode 100644 index 0000000..847801b --- /dev/null +++ b/week-14/task-12-08/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-12-08.cpp) diff --git a/week-14/task-12-08/test/test-12-08.cpp b/week-14/task-12-08/test/test-12-08.cpp new file mode 100644 index 0000000..8926e11 --- /dev/null +++ b/week-14/task-12-08/test/test-12-08.cpp @@ -0,0 +1,39 @@ +#include "gtest/gtest.h" +#include "tokenize.hpp" + +using my_algorithm::tokenize; + +TEST(TokenizeTest, HandlesEmptyString) { + EXPECT_EQ(tokenize("", {' ', ','}), std::vector({})); +} + +TEST(TokenizeTest, HandlesNoDelimiters) { + EXPECT_EQ(tokenize("hello", {}), std::vector({"hello"})); +} + +TEST(TokenizeTest, SingleDelimiterBetweenTokens) { + EXPECT_EQ(tokenize("a,b,c", {','}), std::vector({"a", "b", "c"})); +} + +TEST(TokenizeTest, MultipleDelimitersBetweenTokens) { + EXPECT_EQ(tokenize("hello, world!how?are.you", {' ', ',', '!', '?', '.'}), + std::vector({"hello", "world", "how", "are", "you"})); +} + +TEST(TokenizeTest, LeadingAndTrailingDelimiters) { + EXPECT_EQ(tokenize(" ,,test,,case,, ", {' ', ','}), + std::vector({"test", "case"})); +} + +TEST(TokenizeTest, ConsecutiveDelimiters) { + EXPECT_EQ(tokenize("a,, ,b", {',', ' '}), std::vector({"a", "b"})); +} + +TEST(TokenizeTest, MixedDelimitersAndNoTokens) { + EXPECT_EQ(tokenize(", , ,", {',', ' '}), std::vector({})); +} + +TEST(TokenizeTest, ComplexRealWorldCase) { + EXPECT_EQ(tokenize(" John;Doe,42;New York;USA ", {' ', ',', ';'}), + std::vector({"John", "Doe", "42", "New", "York", "USA"})); +} \ No newline at end of file