nochnoikoshmar1

Untitled

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