Advertisement
RobertDeMilo

Делим проект на файлы

Nov 16th, 2023 (edited)
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 17.70 KB | None | 0 0
  1. main
  2.  
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <iostream>
  6. #include <map>
  7. #include <set>
  8. #include <stdexcept>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include <deque>
  13.  
  14. #include "search_server.h"
  15. #include "string_processing.h"
  16. #include "document.h"
  17. #include "paginator.h"
  18. #include "request_queue.h"
  19. #include "read_input_functions.h"
  20.  
  21. using namespace std;
  22.  
  23. template <typename Container>
  24. auto Paginate(const Container& c, size_t page_size) {
  25.     return Paginator(begin(c), end(c), page_size);
  26. }
  27.  
  28. int main() {
  29.     SearchServer search_server("and in at"s);
  30.  
  31.     RequestQueue request_queue(search_server);
  32.  
  33.     search_server.AddDocument(1, "curly cat curly tail"s, DocumentStatus::ACTUAL, { 7, 2, 7 });
  34.     search_server.AddDocument(2, "curly dog and fancy collar"s, DocumentStatus::ACTUAL, { 1, 2, 3 });
  35.     search_server.AddDocument(3, "big cat fancy collar "s, DocumentStatus::ACTUAL, { 1, 2, 8 });
  36.     search_server.AddDocument(4, "big dog sparrow Eugene"s, DocumentStatus::ACTUAL, { 1, 3, 2 });
  37.     search_server.AddDocument(5, "big dog sparrow Vasiliy"s, DocumentStatus::ACTUAL, { 1, 1, 1 });
  38.  
  39.     // 1439 запросов с нулевым результатом
  40.     for (int i = 0; i < 1439; ++i)
  41.     {
  42.         request_queue.AddFindRequest("empty request"s);
  43.     }
  44.  
  45.     // все еще 1439 запросов с нулевым результатом
  46.     request_queue.AddFindRequest("curly dog"s);
  47.  
  48.     // новые сутки, первый запрос удален, 1438 запросов с нулевым результатом
  49.     request_queue.AddFindRequest("big collar"s);
  50.  
  51.     // первый запрос удален, 1437 запросов с нулевым результатом
  52.     request_queue.AddFindRequest("sparrow"s);
  53.  
  54.     cout << "Total empty requests: "s << request_queue.GetNoResultRequests() << endl;
  55.     return 0;
  56. }
  57. // Total empty requests: 1437
  58. ###########################################################################################################
  59. paginator.h
  60.  
  61. #pragma once
  62.  
  63. #include <vector>
  64. #include <iterator>
  65. #include <iostream>
  66.  
  67. template<typename Iterator>
  68. class IteratorRange
  69. {
  70. public:
  71.  
  72.     IteratorRange(Iterator begin, Iterator end, size_t size)
  73.     {
  74.         begin_ = begin;
  75.         end_ = end;
  76.         size_ = size;
  77.     }
  78.     Iterator begin() const
  79.     {
  80.         return begin_;
  81.     }
  82.     Iterator end() const
  83.     {
  84.         return end_;
  85.     }
  86.  
  87. private:
  88.  
  89.     Iterator begin_;
  90.     Iterator end_;
  91.     size_t size_;
  92. };
  93.  
  94. template<typename Iterator>
  95. std::ostream& operator<<(std::ostream& out, const  IteratorRange <Iterator>& ir)
  96. {
  97.     for (auto it = ir.begin(); it != ir.end(); ++it)
  98.     {
  99.         out << *it;
  100.     }
  101.     return out;
  102. }
  103.  
  104. template<typename Iterator>
  105. IteratorRange<Iterator>& operator*(IteratorRange<Iterator> ir)
  106. {
  107.     return ir;
  108. }
  109.  
  110. template <typename Iterator>
  111. class Paginator
  112. {
  113. public:
  114.     Paginator(Iterator range_begin, Iterator range_end, size_t sizz)
  115.     {
  116.         /*int max_size = range_end - range_begin;*/
  117.         int max_size = distance(range_begin, range_end);
  118.         int size = sizz;
  119.  
  120.         for (auto it = range_begin; it != range_end;)
  121.         {
  122.             int add = min(max_size, size);
  123.  
  124.             auto first = it;
  125.             /*auto second = it + add;*/
  126.             auto second = it;
  127.             advance(second, add);
  128.  
  129.             ir_.push_back({ first , second, sizz });
  130.  
  131.             /*it += add;*/
  132.             advance(it, add);
  133.  
  134.             max_size -= size;
  135.         }
  136.     }
  137.     auto begin() const
  138.     {
  139.         return ir_.begin();
  140.     }
  141.     auto end() const
  142.     {
  143.         return ir_.end();
  144.     }
  145.  
  146. private:
  147.     vector<IteratorRange<Iterator>> ir_;
  148. };
  149.  
  150. ###########################################################################################################
  151. read_input_functions.h
  152.  
  153. #pragma once
  154.  
  155. #include <iostream>
  156. #include "document.h"
  157.  
  158. using namespace std;
  159.  
  160. ostream& operator<< (ostream& out, const Document& document);
  161. ###########################################################################################################
  162. read_input_functions.cpp
  163.  
  164. #include "read_input_functions.h"
  165.  
  166. ostream& operator<< (ostream& out, const Document& document)
  167. {
  168.     out << "{ document_id = "s << document.id << ", relevance = "s << document.relevance
  169.         << ", rating = " << document.rating << " }"s;
  170.  
  171.     return out;
  172. }
  173. ###########################################################################################################
  174. document.h
  175.  
  176. #pragma once
  177.  
  178. struct Document {
  179.     Document() = default;
  180.  
  181.     Document(int id, double relevance, int rating)
  182.         : id(id)
  183.         , relevance(relevance)
  184.         , rating(rating)
  185.     {
  186.     }
  187.  
  188.     int id = 0;
  189.     double relevance = 0.0;
  190.     int rating = 0;
  191. };
  192.  
  193. enum class DocumentStatus {
  194.     ACTUAL,
  195.     IRRELEVANT,
  196.     BANNED,
  197.     REMOVED,
  198. };
  199. ###########################################################################################################
  200. document.cpp
  201. empty
  202. ###########################################################################################################
  203. request_queue.h
  204.  
  205. #pragma once
  206.  
  207. #include <deque>
  208. #include <vector>
  209. #include "search_server.h"
  210.  
  211. using namespace std;
  212.  
  213. class RequestQueue {
  214. public:
  215.     explicit RequestQueue(const SearchServer& search_server);
  216.  
  217.     // сделаем "обёртки" для всех методов поиска, чтобы сохранять результаты для нашей статистики
  218.     template <typename DocumentPredicate>
  219.     vector<Document> AddFindRequest(const string& raw_query, DocumentPredicate document_predicate) {
  220.  
  221.         vector<Document> docs = sr_.FindTopDocuments(raw_query, document_predicate);
  222.         Adjust(requests_);
  223.  
  224.         QueryResult qr;
  225.  
  226.         if (docs.empty())
  227.         {
  228.             qr.time_point += 1;
  229.             qr.is_empty_request = true;
  230.         }
  231.         else
  232.         {
  233.             qr.time_point += 1;
  234.             qr.is_empty_request = false;
  235.         }
  236.  
  237.         requests_.push_back(qr);
  238.         return docs;
  239.     }
  240.     vector<Document> AddFindRequest(const string& raw_query, DocumentStatus status) {
  241.  
  242.         vector<Document> docs = sr_.FindTopDocuments(raw_query, status);
  243.         Adjust(requests_);
  244.  
  245.         QueryResult qr;
  246.  
  247.         if (docs.empty())
  248.         {
  249.             qr.time_point += 1;
  250.             qr.is_empty_request = true;
  251.         }
  252.         else
  253.         {
  254.             qr.time_point += 1;
  255.             qr.is_empty_request = false;
  256.         }
  257.         requests_.push_back(qr);
  258.  
  259.         return docs;
  260.     }
  261.  
  262.     vector<Document> AddFindRequest(const string& raw_query) {
  263.  
  264.         vector<Document> docs = sr_.FindTopDocuments(raw_query);
  265.         Adjust(requests_);
  266.  
  267.         QueryResult qr;
  268.  
  269.         if (docs.empty())
  270.         {
  271.             qr.time_point += 1;
  272.             qr.is_empty_request = true;
  273.         }
  274.         else
  275.         {
  276.             qr.time_point += 1;
  277.             qr.is_empty_request = false;
  278.         }
  279.  
  280.         requests_.push_back(qr);
  281.         return docs;
  282.     }
  283.  
  284.     int GetNoResultRequests() const;
  285.  
  286. private:
  287.     struct QueryResult
  288.     {
  289.         bool is_empty_request;
  290.         static int time_point;
  291.     };
  292.  
  293.     deque<QueryResult> requests_;
  294.  
  295.     const static int min_in_day_ = 1440;
  296.  
  297.     const SearchServer& sr_;
  298.  
  299.     void Adjust(deque<QueryResult>& requests_);
  300. };
  301. ###########################################################################################################
  302. request_queue.cpp
  303.  
  304. #include "request_queue.h"
  305.  
  306. using namespace std;
  307.  
  308. RequestQueue::RequestQueue(const SearchServer& search_server) :sr_(search_server) {}
  309.  
  310. // сделаем "обёртки" для всех методов поиска, чтобы сохранять результаты для нашей статистики
  311.  
  312. int RequestQueue::GetNoResultRequests() const {
  313.     return count_if(requests_.begin(), requests_.end(), [](const RequestQueue::QueryResult& qr)
  314.         { return qr.is_empty_request == true; });
  315.  
  316. }
  317.  
  318. void RequestQueue::Adjust(deque<RequestQueue::QueryResult>& requests_)
  319. {
  320.     if (!requests_.empty() && requests_.back().time_point >= min_in_day_)
  321.     {
  322.         requests_.pop_front();
  323.     }
  324. }
  325.  
  326. int RequestQueue::QueryResult::time_point = 0;
  327. ###########################################################################################################
  328. string_processing.h
  329.  
  330. #pragma once
  331.  
  332. #include <iostream>
  333. #include <vector>
  334. #include <string>
  335.  
  336. using namespace std;
  337.  
  338. string ReadLine();
  339.  
  340. int ReadLineWithNumber();
  341.  
  342. vector<string> SplitIntoWords(const string& text);
  343. ###########################################################################################################
  344. string_processing.cpp
  345.  
  346. #include "string_processing.h"
  347.  
  348. string ReadLine() {
  349.     string s;
  350.     getline(cin, s);
  351.     return s;
  352. }
  353.  
  354. int ReadLineWithNumber() {
  355.     int result;
  356.     cin >> result;
  357.     ReadLine();
  358.     return result;
  359. }
  360.  
  361. vector<string> SplitIntoWords(const string& text) {
  362.     vector<string> words;
  363.     string word;
  364.     for (const char c : text) {
  365.         if (c == ' ') {
  366.             if (!word.empty()) {
  367.                 words.push_back(word);
  368.                 word.clear();
  369.             }
  370.         }
  371.         else {
  372.             word += c;
  373.         }
  374.     }
  375.     if (!word.empty()) {
  376.         words.push_back(word);
  377.     }
  378.  
  379.     return words;
  380. }
  381. ###########################################################################################################
  382. search_server.h
  383.  
  384. #pragma once
  385.  
  386. #include <iostream>
  387. #include <algorithm>
  388. #include <vector>
  389. #include <map>
  390. #include <set>
  391.  
  392. #include "string_processing.h"
  393. #include "document.h"
  394.  
  395. using namespace std;
  396.  
  397. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  398.  
  399. template <typename StringContainer>
  400. set<string> MakeUniqueNonEmptyStrings(const StringContainer& strings) {
  401.     set<string> non_empty_strings;
  402.     for (const string& str : strings) {
  403.         if (!str.empty()) {
  404.             non_empty_strings.insert(str);
  405.         }
  406.     }
  407.     return non_empty_strings;
  408. }
  409.  
  410. class SearchServer {
  411. public:
  412.     template <typename StringContainer>
  413.     explicit SearchServer(const StringContainer& stop_words)
  414.         : stop_words_(MakeUniqueNonEmptyStrings(stop_words))  // Extract non-empty stop words
  415.     {
  416.         if (!all_of(stop_words_.begin(), stop_words_.end(), IsValidWord)) {
  417.             throw invalid_argument("Some of stop words are invalid"s);
  418.         }
  419.     }
  420.  
  421.     explicit SearchServer(const string& stop_words_text)
  422.         : SearchServer(
  423.             SplitIntoWords(stop_words_text))  // Invoke delegating constructor from string container
  424.     {
  425.     }
  426.  
  427.     void AddDocument(int document_id, const string& document, DocumentStatus status,
  428.         const vector<int>& ratings);
  429.  
  430.     template <typename DocumentPredicate>
  431.     vector<Document> FindTopDocuments(const string& raw_query,
  432.         DocumentPredicate document_predicate) const {
  433.         const auto query = ParseQuery(raw_query);
  434.  
  435.         auto matched_documents = FindAllDocuments(query, document_predicate);
  436.  
  437.         sort(matched_documents.begin(), matched_documents.end(),
  438.             [](const Document& lhs, const Document& rhs) {
  439.                 if (abs(lhs.relevance - rhs.relevance) < 1e-6) {
  440.                     return lhs.rating > rhs.rating;
  441.                 }
  442.                 else {
  443.                     return lhs.relevance > rhs.relevance;
  444.                 }
  445.             });
  446.         if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  447.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  448.         }
  449.  
  450.         return matched_documents;
  451.     }
  452.  
  453.     vector<Document> FindTopDocuments(const string& raw_query, DocumentStatus status) const {
  454.         return FindTopDocuments(
  455.             raw_query, [status](int document_id, DocumentStatus document_status, int rating) {
  456.                 return document_status == status;
  457.             });
  458.     }
  459.  
  460.     vector<Document> FindTopDocuments(const string& raw_query) const {
  461.         return FindTopDocuments(raw_query, DocumentStatus::ACTUAL);
  462.     }
  463.  
  464.     int GetDocumentCount() const;
  465.  
  466.     int GetDocumentId(int index) const;
  467.  
  468.     tuple<vector<string>, DocumentStatus> MatchDocument(const string& raw_query,
  469.         int document_id) const;
  470.  
  471. private:
  472.     struct DocumentData {
  473.         int rating;
  474.         DocumentStatus status;
  475.     };
  476.     const set<string> stop_words_;
  477.     map<string, map<int, double>> word_to_document_freqs_;
  478.     map<int, DocumentData> documents_;
  479.     vector<int> document_ids_;
  480.  
  481.     bool IsStopWord(const string& word) const;
  482.  
  483.     static bool IsValidWord(const string& word);
  484.  
  485.     vector<string> SplitIntoWordsNoStop(const string& text) const;
  486.  
  487.     static int ComputeAverageRating(const vector<int>& ratings);
  488.  
  489.     struct QueryWord {
  490.         string data;
  491.         bool is_minus;
  492.         bool is_stop;
  493.     };
  494.  
  495.     QueryWord ParseQueryWord(const string& text) const;
  496.  
  497.     struct Query {
  498.         set<string> plus_words;
  499.         set<string> minus_words;
  500.     };
  501.  
  502.     Query ParseQuery(const string& text) const;
  503.  
  504.     // Existence required
  505.     double ComputeWordInverseDocumentFreq(const string& word) const;
  506.  
  507.     template <typename DocumentPredicate>
  508.     vector<Document> FindAllDocuments(const Query& query,
  509.         DocumentPredicate document_predicate) const {
  510.         map<int, double> document_to_relevance;
  511.         for (const string& word : query.plus_words) {
  512.             if (word_to_document_freqs_.count(word) == 0) {
  513.                 continue;
  514.             }
  515.             const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  516.             for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  517.                 const auto& document_data = documents_.at(document_id);
  518.                 if (document_predicate(document_id, document_data.status, document_data.rating)) {
  519.                     document_to_relevance[document_id] += term_freq * inverse_document_freq;
  520.                 }
  521.             }
  522.         }
  523.  
  524.         for (const string& word : query.minus_words) {
  525.             if (word_to_document_freqs_.count(word) == 0) {
  526.                 continue;
  527.             }
  528.             for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  529.                 document_to_relevance.erase(document_id);
  530.             }
  531.         }
  532.  
  533.         vector<Document> matched_documents;
  534.         for (const auto [document_id, relevance] : document_to_relevance) {
  535.             matched_documents.push_back(
  536.                 { document_id, relevance, documents_.at(document_id).rating });
  537.         }
  538.         return matched_documents;
  539.     }
  540. };
  541. ###########################################################################################################
  542. search_server.cpp
  543.  
  544. #include "search_server.h"
  545.  
  546. void SearchServer::AddDocument(int document_id, const string& document, DocumentStatus status,
  547.     const vector<int>& ratings) {
  548.     if ((document_id < 0) || (documents_.count(document_id) > 0)) {
  549.         throw invalid_argument("Invalid document_id"s);
  550.     }
  551.     const auto words = SplitIntoWordsNoStop(document);
  552.  
  553.     const double inv_word_count = 1.0 / words.size();
  554.     for (const string& word : words) {
  555.         word_to_document_freqs_[word][document_id] += inv_word_count;
  556.     }
  557.     documents_.emplace(document_id, DocumentData{ ComputeAverageRating(ratings), status });
  558.     document_ids_.push_back(document_id);
  559. }
  560.  
  561. int SearchServer::GetDocumentCount() const {
  562.     return documents_.size();
  563. }
  564.  
  565. int SearchServer::GetDocumentId(int index) const {
  566.     return document_ids_.at(index);
  567. }
  568.  
  569. tuple<vector<string>, DocumentStatus> SearchServer::MatchDocument(const string& raw_query,
  570.     int document_id) const {
  571.     const auto query = ParseQuery(raw_query);
  572.  
  573.     vector<string> matched_words;
  574.     for (const string& word : query.plus_words) {
  575.         if (word_to_document_freqs_.count(word) == 0) {
  576.             continue;
  577.         }
  578.         if (word_to_document_freqs_.at(word).count(document_id)) {
  579.             matched_words.push_back(word);
  580.         }
  581.     }
  582.     for (const string& word : query.minus_words) {
  583.         if (word_to_document_freqs_.count(word) == 0) {
  584.             continue;
  585.         }
  586.         if (word_to_document_freqs_.at(word).count(document_id)) {
  587.             matched_words.clear();
  588.             break;
  589.         }
  590.     }
  591.     return { matched_words, documents_.at(document_id).status };
  592. }
  593.  
  594. bool SearchServer::IsStopWord(const string& word) const {
  595.     return stop_words_.count(word) > 0;
  596. }
  597.  
  598. bool SearchServer::IsValidWord(const string& word) {
  599.     // A valid word must not contain special characters
  600.     return none_of(word.begin(), word.end(), [](char c) {
  601.         return c >= '\0' && c < ' ';
  602.         });
  603. }
  604.  
  605. vector<string> SearchServer::SplitIntoWordsNoStop(const string& text) const {
  606.     vector<string> words;
  607.     for (const string& word : SplitIntoWords(text)) {
  608.         if (!IsValidWord(word)) {
  609.             throw invalid_argument("Word "s + word + " is invalid"s);
  610.         }
  611.         if (!IsStopWord(word)) {
  612.             words.push_back(word);
  613.         }
  614.     }
  615.     return words;
  616. }
  617.  
  618. int SearchServer::ComputeAverageRating(const vector<int>& ratings) {
  619.     if (ratings.empty()) {
  620.         return 0;
  621.     }
  622.     int rating_sum = 0;
  623.     for (const int rating : ratings) {
  624.         rating_sum += rating;
  625.     }
  626.     return rating_sum / static_cast<int>(ratings.size());
  627. }
  628.  
  629. SearchServer::QueryWord SearchServer::ParseQueryWord(const string& text) const {
  630.     if (text.empty()) {
  631.         throw invalid_argument("Query word is empty"s);
  632.     }
  633.     string word = text;
  634.     bool is_minus = false;
  635.     if (word[0] == '-') {
  636.         is_minus = true;
  637.         word = word.substr(1);
  638.     }
  639.     if (word.empty() || word[0] == '-' || !IsValidWord(word)) {
  640.         throw invalid_argument("Query word "s + text + " is invalid");
  641.     }
  642.  
  643.     return { word, is_minus, IsStopWord(word) };
  644. }
  645.  
  646. SearchServer::Query SearchServer::ParseQuery(const string& text) const {
  647.     Query result;
  648.     for (const string& word : SplitIntoWords(text)) {
  649.         const auto query_word = ParseQueryWord(word);
  650.         if (!query_word.is_stop) {
  651.             if (query_word.is_minus) {
  652.                 result.minus_words.insert(query_word.data);
  653.             }
  654.             else {
  655.                 result.plus_words.insert(query_word.data);
  656.             }
  657.         }
  658.     }
  659.     return result;
  660. }
  661.  
  662. // Existence required
  663. double SearchServer::ComputeWordInverseDocumentFreq(const string& word) const {
  664.     return log(GetDocumentCount() * 1.0 / word_to_document_freqs_.at(word).size());
  665. }
  666.  
  667.  
  668.  
  669.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement