Advertisement
RobertDeMilo

Дедупликатор документов

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