nochnoikoshmar1

Untitled

Mar 3rd, 2023
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.09 KB | None | 0 0
  1. #include <cmath>
  2. #include <map>
  3. #include <string>
  4. #include <algorithm>
  5. #include <iostream>
  6. #include <set>
  7. #include <utility>
  8. #include <vector>
  9. #include <numeric>
  10. #include <chrono>
  11. using namespace std;
  12.  
  13. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  14. enum class DocumentStatus{
  15.     ACTUAL,
  16.     IRRELEVANT,
  17.     BANNED,
  18.     REMOVED
  19. };
  20. vector<string> SplitIntoWords(const string &text){
  21.     vector<string> words;
  22.     string word;
  23.  
  24.     for(const char &c : text){
  25.         if(c == ' '){
  26.             if(!word.empty()){
  27.                 words.push_back(word);
  28.                 word.clear();
  29.             }
  30.         } else{
  31.             word += c;
  32.         }
  33.     }
  34.     if(!word.empty()){
  35.         words.push_back(word);
  36.     }
  37.     return words;
  38. }
  39. struct Document{
  40.     int id;
  41.     double relevance;
  42.     int rating;
  43. };
  44. class SearchServer{
  45. public:
  46.     void SetStopWords(const string &text){
  47.         for(const string &word : SplitIntoWords(text)){
  48.             stop_words_.insert(word);
  49.         }
  50.     }
  51.     void AddDocument(const int &document_id, const string &document, DocumentStatus status, const vector<int> &ratings){
  52.         ++document_count_;
  53.         vector<string> ex_doc = SplitIntoWordsNoStop(document);
  54.         double counted = (double)ex_doc.size();
  55.         for(const auto &word : ex_doc){
  56.             word_to_document_freqs_[word].insert({document_id,count(ex_doc.begin(), ex_doc.end(), word) / counted});
  57.         }
  58.         if(!ratings.empty()){
  59.             document_ratings_[document_id].rating = ComputeAverageRating(ratings);
  60.             document_ratings_[document_id].status = status;
  61.         } else{
  62.             document_ratings_[document_id].rating = 0;
  63.             document_ratings_[document_id].status = status;
  64.         }
  65.         //document_ratings_[document_id] = {ComputeAverageRating(ratings),status};
  66.         //document_ratings_.emplace(document_id, Status{ComputeAverageRating(ratings), status});
  67.     }
  68.     template<typename FuncPredict>
  69.     vector<Document> FindTopDocuments(const string &raw_query, FuncPredict predict/*=[](int document_id, DocumentStatus status, int rating){return status == DocumentStatus::ACTUAL;}*/) const{
  70.         const double EPSILON = 1e-6;
  71.         const Query query_words = ParseQuery(raw_query);
  72.         vector<Document> matched_documents = FindAllDocuments(query_words, predict);
  73.  
  74.         sort(matched_documents.begin(), matched_documents.end(),            
  75.            
  76.             [EPSILON](const Document &lhs, const Document &rhs){
  77.                 if(abs(lhs.relevance - rhs.relevance) < EPSILON){
  78.                     return lhs.rating > rhs.rating;
  79.                 } else{
  80.                     return lhs.relevance > rhs.relevance;
  81.                 }
  82.             }
  83.         );
  84.         if(matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT){
  85.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  86.         }
  87.         return matched_documents;
  88.     }    
  89.     vector<Document> FindTopDocuments(const string &raw_query, DocumentStatus status = DocumentStatus::ACTUAL) const{
  90.         return FindTopDocuments(raw_query,
  91.             [](int document_id, DocumentStatus status, int rating){
  92.                 return status == DocumentStatus::ACTUAL;
  93.             }
  94.         );
  95.     }
  96.     int GetDocumentCount() const{
  97.         return document_count_;
  98.     };
  99.     tuple<vector<string>, DocumentStatus> MatchDocument(const string &raw_query, int document_id) const{
  100.         vector<string> matched_words;
  101.  
  102.         for(const string &word : ParseQuery(raw_query).plus_words)
  103.             if(word_to_document_freqs_.count(word))
  104.                 if(word_to_document_freqs_.at(word).count(document_id))
  105.                     matched_words.push_back(word);
  106.  
  107.  
  108.         for(const string &word : ParseQuery(raw_query).minus_words)
  109.             if(word_to_document_freqs_.count(word))
  110.                 if(word_to_document_freqs_.at(word).count(document_id)){
  111.                     matched_words.clear();
  112.                     break;
  113.                 }
  114.         return{matched_words, document_ratings_.at(document_id).status};
  115.     };
  116. private:
  117.     struct Query{
  118.         set<string> plus_words;
  119.         set<string> minus_words;
  120.     };
  121.     struct Status{
  122.         int rating;
  123.         DocumentStatus status;
  124.     };
  125.     map<string, map<int, double>> word_to_document_freqs_;
  126.     set<string> stop_words_;
  127.     int document_count_ = 0;
  128.     map<int, Status> document_ratings_;
  129.  
  130.     vector<string> SplitIntoWordsNoStop(const string &text) const{
  131.         vector<string> words;
  132.  
  133.         for(const string &word : SplitIntoWords(text)){
  134.             if(!(stop_words_.count(word) > 0)){
  135.                 words.push_back(word);
  136.             }
  137.         }
  138.         return words;
  139.     }
  140.     Query ParseQueryWord(const set<string> &text) const{
  141.         Query query;
  142.  
  143.         for(auto &word : text){
  144.             if(word[0] == '-'){
  145.                 query.minus_words.insert(word.substr(1));
  146.             } else{
  147.                 query.plus_words.insert(word);
  148.             }
  149.         }
  150.         return query;
  151.     }
  152.     Query ParseQuery(const string &text) const{
  153.         set<string> query_words;
  154.  
  155.         for(const string &word : SplitIntoWordsNoStop(text)){
  156.             query_words.insert(word);
  157.         }
  158.         return ParseQueryWord(query_words);
  159.     }
  160.     double CalcTFIDF(const string query_word, const double tf) const{
  161.         return log(document_count_ / (double)word_to_document_freqs_.at(query_word).size()) * tf;
  162.     }
  163.     template<typename FuncPredict>
  164.     vector<Document> FindAllDocuments(const Query &query_words, FuncPredict predict)const{
  165.         vector<Document> matched_documents;
  166.         map<int, double> document_to_relevance;
  167.  
  168.         for(const auto &query_word : query_words.plus_words){
  169.             if(word_to_document_freqs_.count(query_word)){
  170.                 for(const auto &[id,tf] : word_to_document_freqs_.at(query_word)){
  171.                     if constexpr(is_same_v<FuncPredict, DocumentStatus>){
  172.                         if(predict(id, document_ratings_.at(id).status, document_ratings_.at(id).rating)){
  173.                             document_to_relevance[id] += CalcTFIDF(query_word, tf);
  174.                         }
  175.                     }else{
  176.                         switch(document_ratings_.at(id).status){
  177.                             case DocumentStatus::BANNED:
  178.                                 //FindAllDocuments(query_words,
  179.                                 [](int document_id, DocumentStatus status, int rating){
  180.                                     return status == DocumentStatus::BANNED;
  181.                                 };
  182.                                 //);
  183.                         }
  184.                     }                                        
  185.                 }
  186.             }
  187.         }
  188.         for(const auto &query_word : query_words.minus_words){
  189.             if(word_to_document_freqs_.count(query_word)){
  190.                 for(const auto &[id, tf] : word_to_document_freqs_.at(query_word)){
  191.                     document_to_relevance.erase(id);
  192.                 }
  193.             }
  194.         }
  195.         for(const auto &[document_id, relevance] : document_to_relevance){
  196.             matched_documents.push_back({document_id,relevance,document_ratings_.at(document_id).rating});
  197.         }
  198.         return matched_documents;
  199.     }
  200.     static int ComputeAverageRating(const vector<int> &ratings){
  201.         int sum = 0;
  202.         if(ratings.size() == 0){
  203.             return 0;
  204.         } else{
  205.             for(const int &number : ratings)
  206.                 sum += number;
  207.             return sum / (int)ratings.size();
  208.         }
  209.         return 0;
  210.     }
  211. };
  212. void PrintDocument(const Document &document){
  213.     cout << "{ "s
  214.         << "document_id = "s << document.id << ", "s
  215.         << "relevance = "s << document.relevance << ", "s
  216.         << "rating = "s << document.rating
  217.         << " }"s << endl;
  218. }
  219. int main(){
  220.     SearchServer search_server;
  221.     search_server.SetStopWords("и в на"s);
  222.     search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, {8, -3});
  223.     search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, {7, 2, 7});
  224.     search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1});
  225.     search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, {9});
  226.     cout << "ACTUAL by default:"s << endl;
  227.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s)){
  228.         PrintDocument(document);
  229.     }
  230.     cout << "BANNED:"s << endl;
  231.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::BANNED)){
  232.         PrintDocument(document);
  233.     }
  234.     cout << "Even ids:"s << endl;
  235.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating){ return document_id % 2 == 0; })){
  236.         PrintDocument(document);
  237.     }
  238.     return 0;
  239. }
Advertisement
Add Comment
Please, Sign In to add comment