diff --git a/CMakeLists.txt b/CMakeLists.txt index b3d20a8..0874c59 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-13) foreach(DIR ${DIRS}) add_subdirectory(${DIR}) endforeach() diff --git a/week-13/CMakeLists.txt b/week-13/CMakeLists.txt new file mode 100644 index 0000000..883e1da --- /dev/null +++ b/week-13/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DIRS task-11-10 task-11-16 task-11-11) +foreach(DIR ${DIRS}) + add_subdirectory(${DIR}) +endforeach() diff --git a/week-13/task-11-10/CMakeLists.txt b/week-13/task-11-10/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-13/task-11-10/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-13/task-11-10/include/smth_of.hpp b/week-13/task-11-10/include/smth_of.hpp new file mode 100644 index 0000000..324eb37 --- /dev/null +++ b/week-13/task-11-10/include/smth_of.hpp @@ -0,0 +1,30 @@ +#pragma once +#include + +namespace my_algorithm { + +template + requires std::convertible_to +bool has_one(const Range& range, T&& value) { + return std::ranges::find(range, std::forward(value)) != range.end(); +} + +template + requires(std::convertible_to && ...) +bool any_of(const Range& range, Args&&... args) { + return (has_one(range, std::forward(args)) || ...); +} + +template + requires(std::convertible_to && ...) +bool all_of(const Range& range, Args&&... args) { + return (has_one(range, std::forward(args)) && ...); +} + +template + requires(std::convertible_to && ...) +bool none_of(const Range& range, Args&&... args) { + return (!has_one(range, std::forward(args)) && ...); +} + +} // namespace my_algorithm diff --git a/week-13/task-11-10/test/CMakeLists.txt b/week-13/task-11-10/test/CMakeLists.txt new file mode 100644 index 0000000..4991442 --- /dev/null +++ b/week-13/task-11-10/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-11-10.cpp) diff --git a/week-13/task-11-10/test/test-11-10.cpp b/week-13/task-11-10/test/test-11-10.cpp new file mode 100644 index 0000000..0f611d7 --- /dev/null +++ b/week-13/task-11-10/test/test-11-10.cpp @@ -0,0 +1,68 @@ +#include + +#include + +#include "smth_of.hpp" + +using my_algorithm::all_of; +using my_algorithm::any_of; +using my_algorithm::has_one; +using my_algorithm::none_of; + +TEST(HasOne, Array) { + const std::array a{"one", "two", "three", "four", "five"}; + EXPECT_TRUE(has_one(a, "two")); + EXPECT_FALSE(has_one(a, "six")); +} + +TEST(AnyOfAllOfNoneOf, Vector) { + const std::vector vec = {1, 2, 3, 4, 5}; // NOLINT + + EXPECT_TRUE(any_of(vec, 2, 6)); + EXPECT_FALSE(any_of(vec, 6, 7)); + + EXPECT_TRUE(all_of(vec, 1, 2, 3)); + EXPECT_FALSE(all_of(vec, 1, 2, 6)); + + EXPECT_TRUE(none_of(vec, 6, 7, 8)); + EXPECT_FALSE(none_of(vec, 1, 6, 7)); +} + +TEST(AnyOfAllOfNoneOf, Set) { + const std::set s = {10, 20, 30, 40}; // NOLINT + + EXPECT_TRUE(any_of(s, 20, 50)); + EXPECT_FALSE(any_of(s, 50, 60)); + + EXPECT_TRUE(all_of(s, 10, 20)); + EXPECT_FALSE(all_of(s, 10, 50)); + + EXPECT_TRUE(none_of(s, 50, 60)); + EXPECT_FALSE(none_of(s, 20, 60)); +} + +TEST(AnyOfAllOfNoneOf, List) { + const std::list lst = {5, 10, 15, 20}; // NOLINT + + EXPECT_TRUE(any_of(lst, 10, 25)); + EXPECT_FALSE(any_of(lst, 30, 35)); + + EXPECT_TRUE(all_of(lst, 5, 10)); + EXPECT_FALSE(all_of(lst, 5, 30)); + + EXPECT_TRUE(none_of(lst, 25, 30)); + EXPECT_FALSE(none_of(lst, 10, 30)); +} + +TEST(AnyOfAllOfNoneOf, String) { + const std::string str = "hello"; // NOLINT + + EXPECT_TRUE(any_of(str, 'h', 'x')); + EXPECT_FALSE(any_of(str, 'x', 'y')); + + EXPECT_TRUE(all_of(str, 'h', 'e')); + EXPECT_FALSE(all_of(str, 'h', 'z')); + + EXPECT_TRUE(none_of(str, 'x', 'y')); + EXPECT_FALSE(none_of(str, 'h', 'y')); +} diff --git a/week-13/task-11-11/CMakeLists.txt b/week-13/task-11-11/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-13/task-11-11/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-13/task-11-11/include/transform_if.hpp b/week-13/task-11-11/include/transform_if.hpp new file mode 100644 index 0000000..e8a7ada --- /dev/null +++ b/week-13/task-11-11/include/transform_if.hpp @@ -0,0 +1,15 @@ +#pragma once + +namespace my_algorithm { + +template +void transform_if(InputIt first, InputIt last, OutputIt dest, Fct transform, Pred pred) { + while (first != last) { + if (pred(*first)) { + *(dest++) = transform(*first); + } + ++first; + } +} + +} // namespace my_algorithm diff --git a/week-13/task-11-11/test/CMakeLists.txt b/week-13/task-11-11/test/CMakeLists.txt new file mode 100644 index 0000000..c54734d --- /dev/null +++ b/week-13/task-11-11/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-11-11.cpp) diff --git a/week-13/task-11-11/test/test-11-11.cpp b/week-13/task-11-11/test/test-11-11.cpp new file mode 100644 index 0000000..c1d956c --- /dev/null +++ b/week-13/task-11-11/test/test-11-11.cpp @@ -0,0 +1,83 @@ +#include + +#include + +#include "transform_if.hpp" + +using my_algorithm::transform_if; + +TEST(TransformIfTest, SimpleTransformAndFilter) { + const std::vector input = {1, 2, 3, 4, 5}; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), [](int x) { return x * x; }, + [](int x) { return x % 2 == 0; }); + + const std::vector expected = {4, 16}; + EXPECT_EQ(output, expected); +} + +TEST(TransformIfTest, StringTransformAndFilter) { + const std::vector input = {"apple", "banana", "cherry", "date"}; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), + [](const std::string& s) { + std::string result = s; + std::transform(result.begin(), result.end(), result.begin(), + [](auto&& e) { return std::toupper(e); }); + return result; + }, + [](const std::string& s) { return s.length() > 5; }); // NOLINT + + const std::vector expected = {"BANANA", "CHERRY"}; + EXPECT_EQ(output, expected); +} + +TEST(TransformIfTest, EmptyInputRange) { + constexpr std::vector input; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), [](int x) { return x * 2; }, + [](int x) { return x > 0; }); + + EXPECT_TRUE(output.empty()); +} + +TEST(TransformIfTest, NoElementsSatisfyPredicate) { + const std::vector input = {1, 3, 5, 7}; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), [](int x) { return x * 2; }, + [](int x) { return x % 2 == 0; }); + + EXPECT_TRUE(output.empty()); +} + +TEST(TransformIfTest, AllElementsSatisfyPredicate) { + const std::vector input = {2, 4, 6, 8}; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), [](int x) { return x / 2; }, + [](int x) { return x % 2 == 0; }); + + const std::vector expected = {1, 2, 3, 4}; + EXPECT_EQ(output, expected); +} + +TEST(TransformIfTest, ListInput) { + const std::list input = {10, 20, 30, 40}; + std::vector output; + + transform_if( + input.begin(), input.end(), std::back_inserter(output), [](int x) { return x + 1; }, + [](int x) { return x > 15; }); // NOLINT + + const std::vector expected = {21, 31, 41}; + EXPECT_EQ(output, expected); +} diff --git a/week-13/task-11-16/CMakeLists.txt b/week-13/task-11-16/CMakeLists.txt new file mode 100644 index 0000000..552439e --- /dev/null +++ b/week-13/task-11-16/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(test) diff --git a/week-13/task-11-16/test/CMakeLists.txt b/week-13/task-11-16/test/CMakeLists.txt new file mode 100644 index 0000000..902378d --- /dev/null +++ b/week-13/task-11-16/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-11-16.cpp) diff --git a/week-13/task-11-16/test/test-11-16.cpp b/week-13/task-11-16/test/test-11-16.cpp new file mode 100644 index 0000000..13d67c5 --- /dev/null +++ b/week-13/task-11-16/test/test-11-16.cpp @@ -0,0 +1,64 @@ +#include + +#include +#include +#include + +TEST(Views, Istream) { + std::istringstream input("1 2 3 4 5"); + auto stream_view = std::ranges::views::istream(input); + + std::vector result; + std::ranges::copy(stream_view, std::back_inserter(result)); + const std::vector expected = {1, 2, 3, 4, 5}; + + EXPECT_EQ(result, expected); +} + +TEST(Views, Counted) { + const std::vector vec = {1, 2, 3, 4, 5, 6, 7}; + auto counted_view = std::views::counted(std::ranges::next(vec.begin(), 2), 3); + + const std::vector result(counted_view.begin(), counted_view.end()); + + EXPECT_EQ(result, (std::vector{3, 4, 5})); +} + +TEST(Views, JoinStrings) { + const std::vector words = {"hello", " ", "world"}; + const std::string result = + std::string(std::views::join(words).begin(), std::views::join(words).end()); + + EXPECT_EQ(result, "hello world"); +} + +TEST(Views, JoinNestedVecs) { + const std::vector> nested = {{1, 2}, {3, 4}, {5, 6}}; + auto join_view = nested | std::ranges::views::join; + + const std::vector result(join_view.begin(), join_view.end()); + const std::vector expected = {1, 2, 3, 4, 5, 6}; + + EXPECT_EQ(result, expected); +} + +TEST(Views, Stride) { + const std::vector vec = {1, 2, 3, 4, 5, 6, 7}; + auto stride_view = vec | std::views::stride(2); + + const std::vector result(stride_view.begin(), stride_view.end()); + + EXPECT_EQ(result, (std::vector{1, 3, 5, 7})); +} + +TEST(Views, JoinAndStride) { + const std::vector> nested = {{1, 2}, {3, 4}, {5, 6}, {7, 8}}; + auto join_view = nested | std::ranges::views::join; + auto stride_view = join_view | std::ranges::views::stride(2); + + std::vector result; + std::ranges::copy(stride_view, std::back_inserter(result)); + const std::vector expected = {1, 3, 5, 7}; + + EXPECT_EQ(result, expected); +}