diff --git a/.clang-tidy b/.clang-tidy index d831ed0..f03ac84 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -6,7 +6,8 @@ Checks: ' -readability-identifier-length, -readability-else-after-return, -readability-qualified-auto, - -readability-math-missing-parentheses + -readability-math-missing-parentheses, + -readability-magic-numbers ' CheckOptions: - key: readability-identifier-naming.NamespaceCase diff --git a/CMakeLists.txt b/CMakeLists.txt index b3d20a8..6bd3534 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-16) foreach(DIR ${DIRS}) add_subdirectory(${DIR}) endforeach() diff --git a/week-16/CMakeLists.txt b/week-16/CMakeLists.txt new file mode 100644 index 0000000..ad56c89 --- /dev/null +++ b/week-16/CMakeLists.txt @@ -0,0 +1,4 @@ +set(DIRS task-13-01 task-13-02) +foreach(DIR ${DIRS}) + add_subdirectory(${DIR}) +endforeach() diff --git a/week-16/task-13-01/CMakeLists.txt b/week-16/task-13-01/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-16/task-13-01/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-16/task-13-01/include/bytes-to-hex.hpp b/week-16/task-13-01/include/bytes-to-hex.hpp new file mode 100644 index 0000000..61e84fd --- /dev/null +++ b/week-16/task-13-01/include/bytes-to-hex.hpp @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include +#include +#include + +std::string bytes_to_hex_string(const std::vector& bytes) { + std::ostringstream oss; + oss << std::hex << std::uppercase << std::setfill('0'); + for (uint8_t const byte : bytes) { + oss << std::setw(2) << static_cast(byte); + } + return oss.str(); +} diff --git a/week-16/task-13-01/test/CMakeLists.txt b/week-16/task-13-01/test/CMakeLists.txt new file mode 100644 index 0000000..94007a2 --- /dev/null +++ b/week-16/task-13-01/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-13-01.cpp) diff --git a/week-16/task-13-01/test/test-13-01.cpp b/week-16/task-13-01/test/test-13-01.cpp new file mode 100644 index 0000000..74cb3bb --- /dev/null +++ b/week-16/task-13-01/test/test-13-01.cpp @@ -0,0 +1,56 @@ +#include +#include + +#include "bytes-to-hex.hpp" +#include "gtest/gtest.h" + +TEST(BytesToHexTest, EmptyVector) { + const std::vector input; + EXPECT_EQ(bytes_to_hex_string(input), ""); +} + +TEST(BytesToHexTest, SingleByte) { + EXPECT_EQ(bytes_to_hex_string({0x00}), "00"); + EXPECT_EQ(bytes_to_hex_string({0xFF}), "FF"); + EXPECT_EQ(bytes_to_hex_string({0x0A}), "0A"); + EXPECT_EQ(bytes_to_hex_string({0xA0}), "A0"); +} + +TEST(BytesToHexTest, CommonCases) { + EXPECT_EQ(bytes_to_hex_string({0xBA, 0xAD}), "BAAD"); + EXPECT_EQ(bytes_to_hex_string({0xDE, 0xAD, 0xBE, 0xEF}), "DEADBEEF"); + EXPECT_EQ(bytes_to_hex_string({0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF}), + "0123456789ABCDEF"); +} + +TEST(BytesToHexTest, AllPossibleBytes) { + std::vector all_bytes(256); + for (int i = 0; i < 256; ++i) { + all_bytes[i] = static_cast(i); + } + const std::string result = bytes_to_hex_string(all_bytes); + ASSERT_EQ(result.size(), 512); // 256 bytes * 2 chars + for (int i = 0; i < 256; ++i) { + const std::string byte_str = result.substr(i * 2, 2); + const std::string expected = std::string(1, "0123456789ABCDEF"[i >> 4]) + + std::string(1, "0123456789ABCDEF"[i & 0x0F]); + EXPECT_EQ(byte_str, expected); + } +} + +TEST(BytesToHexTest, CorrectFormatting) { + const std::vector input = {0x1, 0x2, 0x03, 0x10, 0xFF}; + const std::string result = bytes_to_hex_string(input); + EXPECT_EQ(result, "01020310FF"); + EXPECT_TRUE(result.find("01") != std::string::npos); + EXPECT_TRUE(result.find("02") != std::string::npos); +} + +TEST(BytesToHexTest, LargeInput) { + const std::vector large_input(10000, 0xAB); + const std::string result = bytes_to_hex_string(large_input); + EXPECT_EQ(result.size(), 20000); + for (size_t i = 0; i < result.size(); i += 2) { + EXPECT_EQ(result.substr(i, 2), "AB"); + } +} diff --git a/week-16/task-13-02/CMakeLists.txt b/week-16/task-13-02/CMakeLists.txt new file mode 100644 index 0000000..0857059 --- /dev/null +++ b/week-16/task-13-02/CMakeLists.txt @@ -0,0 +1,3 @@ +include_directories(include) + +add_subdirectory(test) diff --git a/week-16/task-13-02/include/pascal-triangle.hpp b/week-16/task-13-02/include/pascal-triangle.hpp new file mode 100644 index 0000000..087ec0d --- /dev/null +++ b/week-16/task-13-02/include/pascal-triangle.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +class PascalsTriangle { +public: + explicit PascalsTriangle(size_t n) : n_(n) {} + + void print(std::ostream& out) { + if (n_ == 0) { + return; + } + if (!calculated_) { + triangle_ = calculate(n_); + calculated_ = true; + } + const size_t max_width = num_digits(max_value(triangle_)); + for (int i = 0; i < n_; ++i) { + out << std::string((n_ - i - 1) * (max_width + 1) / 2, ' '); + for (const int num : triangle_[i]) { + out << std::setw(max_width) << num << ' '; + } + out << '\n'; + } + } + +private: + static std::vector> calculate(size_t n) { + std::vector> triangle(n); + for (int i = 0; i < n; ++i) { + triangle[i].resize(i + 1); + triangle[i][0] = triangle[i][i] = 1; + for (int j = 1; j < i; ++j) { + triangle[i][j] = triangle[i - 1][j - 1] + triangle[i - 1][j]; + } + } + return triangle; + } + static int max_value(const std::vector>& triangle) { + return triangle.back()[triangle.back().size() / 2]; + } + static size_t num_digits(int num) { + size_t res = 0; + while (num > 0) { + num /= 10; + res += 1; + } + return res; + } + + size_t n_; + bool calculated_ = false; + std::vector> triangle_; +}; diff --git a/week-16/task-13-02/test/CMakeLists.txt b/week-16/task-13-02/test/CMakeLists.txt new file mode 100644 index 0000000..f63d643 --- /dev/null +++ b/week-16/task-13-02/test/CMakeLists.txt @@ -0,0 +1 @@ +cpp_test(test-13-02.cpp) diff --git a/week-16/task-13-02/test/test-13-02.cpp b/week-16/task-13-02/test/test-13-02.cpp new file mode 100644 index 0000000..d4f3591 --- /dev/null +++ b/week-16/task-13-02/test/test-13-02.cpp @@ -0,0 +1,46 @@ +#include "gtest/gtest.h" +#include "pascal-triangle.hpp" + +class PascalsTriangleTest : public ::testing::Test { +protected: + static std::string captureOutput(int rows) { + std::stringstream ss; + PascalsTriangle triangle(rows); + triangle.print(ss); + return ss.str(); + } +}; + +TEST_F(PascalsTriangleTest, HandlesZeroRows) { + PascalsTriangle triangle(0); + std::stringstream ss; + triangle.print(ss); + EXPECT_TRUE(ss.str().empty()); +} + +TEST_F(PascalsTriangleTest, HandlesSingleRow) { + auto output = captureOutput(1); + EXPECT_EQ(output, "1 \n"); +} + +TEST_F(PascalsTriangleTest, HandlesMultipleRows) { + auto output = captureOutput(3); + const std::string expected = + " 1 \n" + " 1 1 \n" + "1 2 1 \n"; + EXPECT_EQ(output, expected); +} + +TEST_F(PascalsTriangleTest, OutputFormatting) { + auto output = captureOutput(5); // NOLINT + const std::string expected = + " 1 \n" + " 1 1 \n" + " 1 2 1 \n" + " 1 3 3 1 \n" + "1 4 6 4 1 \n"; + EXPECT_EQ(output, expected); +} + +TEST_F(PascalsTriangleTest, JustPrintATriangle) { PascalsTriangle(10).print(std::cout); }