Advertisement
chevengur

СПРИНТ № 5 | Распределение кода по файлам | Делим проект на файлы

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