Advertisement
DanilaK

test for task domens

Mar 30th, 2020
1,242
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.21 KB | None | 0 0
  1. #include "test_runner.h"
  2. #include "profile.h"
  3.  
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <optional>
  7. #include <string>
  8. #include <string_view>
  9. #include <vector>
  10.  
  11. using namespace std;
  12.  
  13. template <typename It>
  14. class Range {
  15. public:
  16.   Range(It begin, It end) : begin_(begin), end_(end) {}
  17.   It begin() const { return begin_; }
  18.   It end() const { return end_; }
  19.  
  20. private:
  21.   It begin_;
  22.   It end_;
  23. };
  24.  
  25. pair<string_view, optional<string_view>> SplitTwoStrict(string_view s, string_view delimiter = " ") {
  26.   const size_t pos = s.find(delimiter);
  27.   if (pos == s.npos) {
  28.     return {s, nullopt};
  29.   } else {
  30.     return {s.substr(0, pos), s.substr(pos + delimiter.length())};
  31.   }
  32. }
  33.  
  34. vector<string_view> Split(string_view s, string_view delimiter = " ") {
  35.   vector<string_view> parts;
  36.   if (s.empty()) {
  37.     return parts;
  38.   }
  39.   while (true) {
  40.     const auto [lhs, rhs_opt] = SplitTwoStrict(s, delimiter);
  41.     parts.push_back(lhs);
  42.     if (!rhs_opt) {
  43.       break;
  44.     }
  45.     s = *rhs_opt;
  46.   }
  47.   return parts;
  48. }
  49.  
  50.  
  51. class Domain {
  52. public:
  53.   explicit Domain(string_view text) {
  54.     vector<string_view> parts = Split(text, ".");
  55.     parts_reversed_.assign(rbegin(parts), rend(parts));
  56.   }
  57.  
  58.   size_t GetPartCount() const {
  59.     return parts_reversed_.size();
  60.   }
  61.  
  62.   auto GetParts() const {
  63.     return Range(rbegin(parts_reversed_), rend(parts_reversed_));
  64.   }
  65.   auto GetReversedParts() const {
  66.     return Range(begin(parts_reversed_), end(parts_reversed_));
  67.   }
  68.  
  69.   bool operator==(const Domain& other) const {
  70.     return parts_reversed_ == other.parts_reversed_;
  71.   }
  72.  
  73. private:
  74.   vector<string> parts_reversed_;
  75. };
  76.  
  77. ostream& operator<<(ostream& stream, const Domain& domain) {
  78.   bool first = true;
  79.   for (const string_view part : domain.GetParts()) {
  80.     if (!first) {
  81.       stream << '.';
  82.     } else {
  83.       first = false;
  84.     }
  85.     stream << part;
  86.   }
  87.   return stream;
  88. }
  89.  
  90. // domain is subdomain of itself
  91. bool IsSubdomain(const Domain& subdomain, const Domain& domain) {
  92.   const auto subdomain_reversed_parts = subdomain.GetReversedParts();
  93.   const auto domain_reversed_parts = domain.GetReversedParts();
  94.   return
  95.       subdomain.GetPartCount() >= domain.GetPartCount()
  96.       && equal(begin(domain_reversed_parts), end(domain_reversed_parts),
  97.                begin(subdomain_reversed_parts));
  98. }
  99.  
  100. bool IsSubOrSuperDomain(const Domain& lhs, const Domain& rhs) {
  101.   return lhs.GetPartCount() >= rhs.GetPartCount()
  102.          ? IsSubdomain(lhs, rhs)
  103.          : IsSubdomain(rhs, lhs);
  104. }
  105.  
  106.  
  107. class DomainChecker {
  108. public:
  109.   template <typename InputIt>
  110.   DomainChecker(InputIt domains_begin, InputIt domains_end) {
  111.     sorted_domains_.reserve(distance(domains_begin, domains_end));
  112.     for (const Domain& domain : Range(domains_begin, domains_end)) {
  113.       sorted_domains_.push_back(&domain);
  114.     }
  115.     sort(begin(sorted_domains_), end(sorted_domains_), IsDomainLess);
  116.     sorted_domains_ = AbsorbSubdomains(move(sorted_domains_));
  117.   }
  118.  
  119.   // Check if candidate is subdomain of some domain
  120.   bool IsSubdomain(const Domain& candidate) const {
  121.     const auto it = upper_bound(
  122.         begin(sorted_domains_), end(sorted_domains_),
  123.         &candidate, IsDomainLess);
  124.     if (it == begin(sorted_domains_)) {
  125.       return false;
  126.     }
  127.     return ::IsSubdomain(candidate, **prev(it));
  128.   }
  129.  
  130. private:
  131.   vector<const Domain*> sorted_domains_;
  132.  
  133.   static bool IsDomainLess(const Domain* lhs, const Domain* rhs) {
  134.     const auto lhs_reversed_parts = lhs->GetReversedParts();
  135.     const auto rhs_reversed_parts = rhs->GetReversedParts();
  136.     return lexicographical_compare(
  137.       begin(lhs_reversed_parts), end(lhs_reversed_parts),
  138.       begin(rhs_reversed_parts), end(rhs_reversed_parts)
  139.     );
  140.   }
  141.  
  142.   static vector<const Domain*> AbsorbSubdomains(vector<const Domain*> domains) {
  143.     domains.erase(
  144.         unique(begin(domains), end(domains),
  145.                [](const Domain* lhs, const Domain* rhs) {
  146.                  return IsSubOrSuperDomain(*lhs, *rhs);
  147.                }),
  148.         end(domains)
  149.     );
  150.     return domains;
  151.   }
  152. };
  153.  
  154.  
  155. vector<Domain> ReadDomains(istream& in_stream = cin) {
  156.   vector<Domain> domains;
  157.  
  158.   size_t count;
  159.   in_stream >> count;
  160.   domains.reserve(count);
  161.  
  162.   for (size_t i = 0; i < count; ++i) {
  163.     string domain_text;
  164.     in_stream >> domain_text;
  165.     domains.emplace_back(domain_text);
  166.   }
  167.   return domains;
  168. }
  169.  
  170. vector<bool> CheckDomains(const vector<Domain>& banned_domains, const vector<Domain>& domains_to_check) {
  171.   const DomainChecker checker(begin(banned_domains), end(banned_domains));
  172.  
  173.   vector<bool> check_results;
  174.   check_results.reserve(domains_to_check.size());
  175.   for (const Domain& domain_to_check : domains_to_check) {
  176.     check_results.push_back(!checker.IsSubdomain(domain_to_check));
  177.   }
  178.  
  179.   return check_results;
  180. }
  181.  
  182. void PrintCheckResults(const vector<bool>& check_results, ostream& out_stream = cout) {
  183.   for (const bool check_result : check_results) {
  184.     out_stream << (check_result ? "Good" : "Bad") << "\n";
  185.   }
  186. }
  187.  
  188. void Test1_parts() {
  189.     Domain d0("ru");
  190.     ASSERT_EQUAL(d0.GetPartCount(), 1)
  191.     vector<string_view> v0{ d0.GetParts().begin(), d0.GetParts().end() };
  192.     ASSERT_EQUAL(v0.size(), 1)
  193.     ASSERT_EQUAL(string(v0[0]), "ru")
  194.  
  195.     Domain d1("az.bz.cz");
  196.     ASSERT_EQUAL(d1.GetPartCount(), 3)
  197.     vector<string_view> v1{ d1.GetParts().begin(), d1.GetParts().end() };
  198.     ASSERT_EQUAL(v1.size(), 3)
  199.     ASSERT_EQUAL(string(v1[0]), "az")
  200.     ASSERT_EQUAL(string(v1[1]), "bz")
  201.     ASSERT_EQUAL(string(v1[2]), "cz")
  202. }
  203.  
  204. void Test2_reversed_parts() {
  205.     Domain d0("ru");
  206.     vector<string_view> v0{ d0.GetReversedParts().begin(), d0.GetReversedParts().end() };
  207.     ASSERT_EQUAL(v0.size(), 1)
  208.     ASSERT_EQUAL(string(v0[0]), "ru")
  209.  
  210.     Domain d1("az.bz.cz");
  211.     vector<string_view> v1{ d1.GetReversedParts().begin(), d1.GetReversedParts().end() };
  212.     ASSERT_EQUAL(string(v1[0]), "cz")
  213.     ASSERT_EQUAL(string(v1[1]), "bz")
  214.     ASSERT_EQUAL(string(v1[2]), "az")
  215. }
  216.  
  217. void Test3_subdomain_of_itself() {
  218.     Domain d1("com");
  219.     Domain d2("a.b.ru");
  220.     Domain d3("mail.com");
  221.     Domain d4("com.com.com");
  222.  
  223.     ASSERT(IsSubdomain(d1, d1))
  224.     ASSERT(IsSubdomain(d2, d2))
  225.     ASSERT(IsSubdomain(d3, d3))
  226.     ASSERT(IsSubdomain(d4, d4))    
  227. }
  228.  
  229. void Test4_subdomain_swapped() {
  230.     Domain d1("com");    
  231.     Domain d2("mail.com");
  232.     Domain d3("mailcom");
  233.     Domain d4("com.com.com");
  234.     Domain d5("com.mail");
  235.  
  236.     ASSERT(IsSubdomain(d1, d1))
  237.     ASSERT(IsSubdomain(d2, d1))
  238.     ASSERT(IsSubdomain(d4, d1))
  239.     ASSERT(!IsSubdomain(d1, d2))
  240.     ASSERT(!IsSubdomain(d1, d3))
  241.     ASSERT(!IsSubdomain(d1, d4))
  242.     ASSERT(!IsSubdomain(d2, d3))
  243.     ASSERT(!IsSubdomain(d3, d2))
  244.     ASSERT(!IsSubdomain(d5, d2))
  245.     ASSERT(!IsSubdomain(d2, d5))
  246. }
  247.  
  248. void Test4b_IsSubOrSuperDomain() {
  249.     Domain d1("ru");
  250.     Domain d2("com");
  251.     Domain d3("mail.com");
  252.     Domain d4("mailcom");
  253.  
  254.     ASSERT(IsSubOrSuperDomain(d2, d2))
  255.     ASSERT(!IsSubOrSuperDomain(d1, d2))
  256.     ASSERT(!IsSubOrSuperDomain(d2, d1))
  257.     ASSERT(IsSubOrSuperDomain(d3, d2))
  258.     ASSERT(IsSubOrSuperDomain(d2, d3))
  259.     ASSERT(!IsSubOrSuperDomain(d4, d3))
  260.     ASSERT(!IsSubOrSuperDomain(d3, d4))
  261. }
  262.  
  263. void Test5_DomainChecker_IsSubdomain() {
  264.     vector<Domain> test_banned_domains{ Domain("ru"), Domain("mail.cc") };
  265.     DomainChecker checker(begin(test_banned_domains), end(test_banned_domains));
  266.     ASSERT(checker.IsSubdomain(Domain("mail.ya.ru")))
  267.     ASSERT(!checker.IsSubdomain(Domain("mail.yaru")))
  268.     ASSERT(checker.IsSubdomain(Domain("mail.cc")))
  269.     ASSERT(checker.IsSubdomain(Domain("ys.mail.cc")))
  270.     ASSERT(!checker.IsSubdomain(Domain("ysmail.cc")))
  271.     ASSERT(!checker.IsSubdomain(Domain("ma.il.cc")))
  272.     ASSERT(!checker.IsSubdomain(Domain("mailcc")))
  273.     ASSERT(!checker.IsSubdomain(Domain("ru.cc")))
  274.     ASSERT(!checker.IsSubdomain(Domain("cc.mail")))
  275.     ASSERT(!checker.IsSubdomain(Domain("cc.liam")))
  276.     ASSERT(!checker.IsSubdomain(Domain("ru.mail")))
  277.     ASSERT(!checker.IsSubdomain(Domain("ru.cc")))    
  278. }
  279.  
  280. void Test6_check_domains() {
  281.     vector<bool> results1 = CheckDomains(
  282.         {Domain("ru"), Domain("ya.ru"), Domain("com"), Domain("mail.cc"), Domain("ru.su")},
  283.         { Domain("me"), Domain("mail.yaru"), Domain("com"), Domain("mailyaru"), Domain("com.com") });
  284.     vector<bool> expected1{ true, true, false, true, false };
  285.     ASSERT_EQUAL(results1, expected1)
  286.    
  287.  
  288.     vector<bool> results2 = CheckDomains(
  289.         { Domain("ya.ya"), Domain("ya.ru"), Domain("ya.com") },
  290.         { Domain("haya.ya"), Domain("teya.ru"), Domain("suya.com"), Domain("ha.ya.ya"), Domain("te.ya.ru"), Domain("su.ya.com") });
  291.     vector<bool> expected2{ true, true, true, false, false, false };
  292.     ASSERT_EQUAL(results2, expected2)
  293.  
  294.  
  295.     vector<bool> results3 = CheckDomains(
  296.         { Domain("ya.ru"), Domain("maps.me"), Domain("m.ya.ru"), Domain("com")},
  297.         { Domain("ya.ru"), Domain("ya.com"), Domain("m.maps.me"), Domain("moscow.m.ya.ru"), Domain("maps.com"), Domain("maps.ru"), Domain("ya.ya") });
  298.     vector<bool> expected3{ false, false, false, false, false, true, true };
  299.     ASSERT_EQUAL(results3, expected3)
  300.  
  301.  
  302.     vector<bool> results4 = CheckDomains(
  303.         {},
  304.         { Domain("ya.ru"), Domain("ya.com"), Domain("m.maps.me"), Domain("moscow.m.ya.ru"), Domain("maps.com"), Domain("maps.ru"), Domain("ya.ya") });
  305.     vector<bool> expected4{ true, true, true, true, true, true, true };
  306.     ASSERT_EQUAL(results4, expected4)
  307. }
  308.  
  309. void Test7_print_check_results() {
  310.     stringstream ss;
  311.     PrintCheckResults({ true, false }, ss);
  312.     string s1, s2;
  313.     ss >> s1 >> s2;
  314.     ASSERT_EQUAL(s1, "Good");
  315.     ASSERT_EQUAL(s2, "Bad");
  316. }
  317.  
  318. void Test8_read_domains() {
  319.     stringstream ss;
  320.     ss << "7\n" << "am\n" << "bm.am\n" << "cm.bm.am\n" << "dm.cm.bm.am\n" << "em.dm.cm.bm.am\n" << "am.am\n" << "am.am.am\n";
  321.     vector<Domain> domains = ReadDomains(ss);
  322.     ASSERT_EQUAL(domains.size(), 7);
  323.     ASSERT_EQUAL(domains[0], Domain("am"));
  324.     ASSERT_EQUAL(domains[1], Domain("bm.am"));
  325.     ASSERT_EQUAL(domains[2], Domain("cm.bm.am"));
  326.     ASSERT_EQUAL(domains[3], Domain("dm.cm.bm.am"));
  327.     ASSERT_EQUAL(domains[4], Domain("em.dm.cm.bm.am"));
  328.     ASSERT_EQUAL(domains[5], Domain("am.am"));
  329.     ASSERT_EQUAL(domains[6], Domain("am.am.am"));
  330.  
  331.     ss.clear();
  332.     ss << "0\n";
  333.     domains = ReadDomains(ss);
  334.     ASSERT_EQUAL(domains.size(), 0);
  335.    
  336.     ss.clear();
  337.     ss << "1\n" << "am.am.am\n";
  338.     domains = ReadDomains(ss);
  339.     ASSERT_EQUAL(domains.size(), 1);
  340.     ASSERT_EQUAL(domains[0], Domain("am.am.am"));
  341. }
  342.  
  343. void Test9_full() {
  344.     stringstream ss_in, ss_out;
  345.  
  346.     ss_in << "4\n";
  347.     ss_in << "ya.ru\n" << "maps.me\n" << "m.ya.ru\n" << "com\n";
  348.     ss_in << "7\n";
  349.     ss_in << "ya.ru\n" << "ya.com\n" << "m.maps.me\n" << "moscow.m.ya.ru\n" << "maps.com\n" << "maps.ru\n" << "ya.ya\n";
  350.  
  351.     const vector<Domain> banned_domains = ReadDomains(ss_in);
  352.     const vector<Domain> domains_to_check = ReadDomains(ss_in);
  353.     PrintCheckResults(CheckDomains(banned_domains, domains_to_check), ss_out);
  354.     ASSERT_EQUAL(ss_out.str(), "Bad\nBad\nBad\nBad\nBad\nGood\nGood\n");
  355.  
  356.  
  357.     stringstream ss_in2, ss_out2;
  358.  
  359.     ss_in2 << "3\n";
  360.     ss_in2 << "ya.ya\n" << "ya.ru\n" << "ya.com\n";
  361.     ss_in2 << "7\n";
  362.     ss_in2 << "ha.ya.ya\n" << "te.ya.ru\n" << "su.ya.com\n" << "haya.ya\n" << "teya.ru\n" << "suya.com\n" << "ya.ya.net\n";
  363.  
  364.     const vector<Domain> banned_domains2 = ReadDomains(ss_in2);
  365.     const vector<Domain> domains_to_check2 = ReadDomains(ss_in2);
  366.     PrintCheckResults(CheckDomains(banned_domains2, domains_to_check2), ss_out2);
  367.     ASSERT_EQUAL(ss_out2.str(), "Bad\nBad\nBad\nGood\nGood\nGood\nGood\n");
  368. }
  369.  
  370. void TestSimple() {
  371.     // Your tests here
  372.     Test1_parts();
  373.     Test2_reversed_parts();
  374.     Test3_subdomain_of_itself();
  375.     Test4_subdomain_swapped();
  376.     Test4b_IsSubOrSuperDomain();
  377.     Test5_DomainChecker_IsSubdomain();
  378.     Test6_check_domains();
  379.     Test7_print_check_results();
  380.     Test8_read_domains();
  381.     Test9_full();
  382.  }
  383.  
  384. int main() {
  385.     TestRunner tr;
  386.     RUN_TEST(tr, TestSimple);
  387.  
  388.     const vector<Domain> banned_domains = ReadDomains();
  389.     const vector<Domain> domains_to_check = ReadDomains();
  390.     PrintCheckResults(CheckDomains(banned_domains, domains_to_check));
  391.     return 0;
  392. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement