shushus

Спринт 16. Начнем с простого.

Jun 20th, 2023
656
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.80 KB | None | 0 0
  1. -----------------------------------------------------------------------
  2. common.h
  3. -----------------------------------------------------------------------
  4. #pragma once
  5.  
  6. #include <sstream>
  7. #include <string>
  8. #include <string_view>
  9.  
  10. struct Position {
  11.     int row = 0;
  12.     int col = 0;
  13.  
  14.     bool operator==(Position rhs) const;
  15.     bool operator<(Position rhs) const;
  16.  
  17.     bool IsValid() const;
  18.     std::string ToString() const;
  19.  
  20.     static Position FromString(std::string_view str);
  21.  
  22.     static const int MAX_ROWS = 16384;
  23.     static const int MAX_COLS = 16384;
  24.     static const Position NONE;
  25. };
  26. -----------------------------------------------------------------------
  27. structures.cpp
  28. -----------------------------------------------------------------------
  29. #include "common.h"
  30.  
  31. #include <algorithm>
  32. #include <cctype>
  33. #include <sstream>
  34.  
  35. const int LETTERS = 26;
  36. const int MAX_POSITION_LENGTH = 17;
  37. const int MAX_POS_LETTER_COUNT = 3;
  38.  
  39. const Position Position::NONE = {-1, -1};
  40.  
  41. bool Position::operator==(const Position rhs) const {return (row == rhs.row) && (col == rhs.col);}
  42. bool Position::operator<(const Position rhs) const {return std::make_tuple(row, col) < std::make_tuple(rhs.row, rhs.col);}
  43. bool Position::IsValid() const {return (row >= 0 && col >= 0) && (row < MAX_ROWS && col < MAX_COLS);}
  44.  
  45. std::string Position::ToString() const {
  46.    
  47.     if (IsValid()) {
  48.        
  49.         std::string converted_string;
  50.        
  51.         int columns = col;
  52.         while (columns >= 0) {
  53.             converted_string.insert(converted_string.begin(), 'A' + columns % LETTERS);
  54.             columns = columns / LETTERS - 1;
  55.         }
  56.  
  57.         converted_string += std::to_string(row + 1);
  58.         return converted_string;
  59.        
  60.     } else {
  61.         return "";
  62.     }  
  63. }
  64.  
  65. Position Position::FromString(std::string_view str) {
  66.    
  67.     auto it = std::find_if(str.begin(), str.end(), [](const char c) {
  68.         return !(std::isalpha(c) && std::isupper(c));
  69.     });
  70.    
  71.     auto letters = str.substr(0, it - str.begin());
  72.     auto digits = str.substr(it - str.begin());
  73.  
  74.     if ((letters.empty() || digits.empty())
  75.         || (letters.size() > MAX_POS_LETTER_COUNT)
  76.         || (std::isdigit(digits[0]) == 0)) {
  77.        
  78.         return Position::NONE;
  79.        
  80.     }
  81.    
  82.     int row = 0;
  83.     std::istringstream row_in{std::string{digits}};
  84.        
  85.     if (!(row_in >> row) || !row_in.eof()) {
  86.         return Position::NONE;
  87.     }
  88.  
  89.     int col = 0;
  90.     for (char ch : letters) {
  91.         col *= LETTERS;
  92.         col += ch - 'A' + 1;
  93.     }
  94.  
  95.     return {row - 1, col - 1};
  96. }
  97. -----------------------------------------------------------------------
  98. test_runner_p.h
  99. -----------------------------------------------------------------------
  100. #pragma once
  101.  
  102. #include <iostream>
  103. #include <map>
  104. #include <set>
  105. #include <sstream>
  106. #include <stdexcept>
  107. #include <string>
  108. #include <unordered_map>
  109. #include <vector>
  110.  
  111. namespace TestRunnerPrivate {
  112.   template <typename K, typename V, template <typename, typename> class Map>
  113.   std::ostream& PrintMap(std::ostream& os, const Map<K, V>& m) {
  114.     os << "{";
  115.     bool first = true;
  116.     for (const auto& kv : m) {
  117.       if (!first) {
  118.         os << ", ";
  119.       }
  120.       first = false;
  121.       os << kv.first << ": " << kv.second;
  122.     }
  123.     return os << "}";
  124.   }
  125. }
  126.  
  127. template <class T>
  128. std::ostream& operator<<(std::ostream& os, const std::vector<T>& s) {
  129.   os << "{";
  130.   bool first = true;
  131.   for (const auto& x : s) {
  132.     if (!first) {
  133.       os << ", ";
  134.     }
  135.     first = false;
  136.     os << x;
  137.   }
  138.   return os << "}";
  139. }
  140.  
  141. template <class T>
  142. std::ostream& operator<<(std::ostream& os, const std::set<T>& s) {
  143.   os << "{";
  144.   bool first = true;
  145.   for (const auto& x : s) {
  146.     if (!first) {
  147.       os << ", ";
  148.     }
  149.     first = false;
  150.     os << x;
  151.   }
  152.   return os << "}";
  153. }
  154.  
  155. template <class K, class V>
  156. std::ostream& operator<<(std::ostream& os, const std::map<K, V>& m) {
  157.   return TestRunnerPrivate::PrintMap(os, m);
  158. }
  159.  
  160. template <class K, class V>
  161. std::ostream& operator<<(std::ostream& os, const std::unordered_map<K, V>& m) {
  162.   return TestRunnerPrivate::PrintMap(os, m);
  163. }
  164.  
  165. template <class T, class U>
  166. void AssertEqual(const T& t, const U& u, const std::string& hint = {}) {
  167.   if (!(t == u)) {
  168.     std::ostringstream os;
  169.     os << "Assertion failed: " << t << " != " << u;
  170.     if (!hint.empty()) {
  171.       os << " hint: " << hint;
  172.     }
  173.     throw std::runtime_error(os.str());
  174.   }
  175. }
  176.  
  177. inline void Assert(bool b, const std::string& hint) {
  178.   AssertEqual(b, true, hint);
  179. }
  180.  
  181. class TestRunner {
  182. public:
  183.   template <class TestFunc>
  184.   void RunTest(TestFunc func, const std::string& test_name) {
  185.     try {
  186.       func();
  187.       std::cerr << test_name << " OK" << std::endl;
  188.     } catch (std::exception& e) {
  189.       ++fail_count;
  190.       std::cerr << test_name << " fail: " << e.what() << std::endl;
  191.     } catch (...) {
  192.       ++fail_count;
  193.       std::cerr << "Unknown exception caught" << std::endl;
  194.     }
  195.   }
  196.  
  197.   ~TestRunner() {
  198.     std::cerr.flush();
  199.     if (fail_count > 0) {
  200.       std::cerr << fail_count << " unit tests failed. Terminate" << std::endl;
  201.       exit(1);
  202.     }
  203.   }
  204.  
  205. private:
  206.   int fail_count = 0;
  207. };
  208.  
  209. #ifndef FILE_NAME
  210. #define FILE_NAME __FILE__
  211. #endif
  212.  
  213. #define ASSERT_EQUAL(x, y)                                               \
  214.   {                                                                      \
  215.     std::ostringstream __assert_equal_private_os;                        \
  216.     __assert_equal_private_os << #x << " != " << #y << ", " << FILE_NAME \
  217.                               << ":" << __LINE__;                        \
  218.     AssertEqual(x, y, __assert_equal_private_os.str());                  \
  219.   }
  220.  
  221. #define ASSERT(x)                                                  \
  222.   {                                                                \
  223.     std::ostringstream __assert_private_os;                        \
  224.     __assert_private_os << #x << " is false, " << FILE_NAME << ":" \
  225.                         << __LINE__;                               \
  226.     Assert(x, __assert_private_os.str());                          \
  227.   }
  228.  
  229. #define RUN_TEST(tr, func) tr.RunTest(func, #func)
  230. -----------------------------------------------------------------------
  231. main.cpp
  232. -----------------------------------------------------------------------
  233. #include "common.h"
  234. #include "test_runner_p.h"
  235.  
  236. #include <iostream>
  237. #include <string>
  238. #include <string_view>
  239.  
  240. inline std::ostream& operator<<(std::ostream& output, Position pos) {
  241.     return output << "(" << pos.row << ", " << pos.col << ")";
  242. }
  243.  
  244. inline Position operator"" _pos(const char* str, std::size_t) {
  245.     return Position::FromString(str);
  246. }
  247.  
  248. namespace {
  249. void TestPositionAndStringConversion() {
  250.     auto test_single = [](Position pos, std::string_view str) {
  251.         ASSERT_EQUAL(pos.ToString(), str);
  252.         ASSERT_EQUAL(Position::FromString(str), pos);
  253.     };
  254.  
  255.     for (int i = 0; i < 25; ++i) {
  256.         test_single(Position{i, i}, char('A' + i) + std::to_string(i + 1));
  257.     }
  258.  
  259.     test_single(Position{0, 0}, "A1");
  260.     test_single(Position{0, 1}, "B1");
  261.     test_single(Position{0, 25}, "Z1");
  262.     test_single(Position{0, 26}, "AA1");
  263.     test_single(Position{0, 27}, "AB1");
  264.     test_single(Position{0, 51}, "AZ1");
  265.     test_single(Position{0, 52}, "BA1");
  266.     test_single(Position{0, 53}, "BB1");
  267.     test_single(Position{0, 77}, "BZ1");
  268.     test_single(Position{0, 78}, "CA1");
  269.     test_single(Position{0, 701}, "ZZ1");
  270.     test_single(Position{0, 702}, "AAA1");
  271.     test_single(Position{136, 2}, "C137");
  272.     test_single(Position{Position::MAX_ROWS - 1, Position::MAX_COLS - 1}, "XFD16384");
  273. }
  274.  
  275. void TestPositionToStringInvalid() {
  276.     ASSERT_EQUAL((Position::NONE).ToString(), "");
  277.     ASSERT_EQUAL((Position{-10, 0}).ToString(), "");
  278.     ASSERT_EQUAL((Position{1, -3}).ToString(), "");
  279. }
  280.  
  281. void TestStringToPositionInvalid() {
  282.     ASSERT(!Position::FromString("").IsValid());
  283.     ASSERT(!Position::FromString("A").IsValid());
  284.     ASSERT(!Position::FromString("1").IsValid());
  285.     ASSERT(!Position::FromString("e2").IsValid());
  286.     ASSERT(!Position::FromString("A0").IsValid());
  287.     ASSERT(!Position::FromString("A-1").IsValid());
  288.     ASSERT(!Position::FromString("A+1").IsValid());
  289.     ASSERT(!Position::FromString("R2D2").IsValid());
  290.     ASSERT(!Position::FromString("C3PO").IsValid());
  291.     ASSERT(!Position::FromString("XFD16385").IsValid());
  292.     ASSERT(!Position::FromString("XFE16384").IsValid());
  293.     ASSERT(!Position::FromString("A1234567890123456789").IsValid());
  294.     ASSERT(!Position::FromString("ABCDEFGHIJKLMNOPQRS8").IsValid());
  295. }
  296.    
  297. }//end namespace
  298.  
  299. int main() {
  300.     TestRunner tr;
  301.     RUN_TEST(tr, TestPositionAndStringConversion);
  302.     RUN_TEST(tr, TestPositionToStringInvalid);
  303.     RUN_TEST(tr, TestStringToPositionInvalid);
  304.     return 0;
  305. }
Advertisement
Add Comment
Please, Sign In to add comment