nochnoikoshmar1

Untitled

Feb 28th, 2023
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.12 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 word += c;
  31.     }
  32.  
  33.     if(!word.empty())
  34.         words.push_back(word);
  35.     return words;
  36. }
  37. struct Document{
  38.     int id;
  39.     double relevance;
  40.     int rating;
  41. };
  42. class SearchServer{
  43. public:
  44.     void SetStopWords(const string &text){
  45.         for(const string &word : SplitIntoWords(text))
  46.             stop_words_.insert(word);
  47.     }
  48.     void AddDocument(const int &document_id, const string &document, DocumentStatus status, const vector<int> &ratings){
  49.         ++document_count_;
  50.         vector<string> ex_doc = SplitIntoWordsNoStop(document);
  51.         double counted = (double)ex_doc.size();
  52.         for(const auto &word : ex_doc){
  53.             word_to_document_freqs_[word].insert({
  54.                 document_id,
  55.                 count(ex_doc.begin(), ex_doc.end(), word) / counted
  56.                 });
  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.     auto FindTopDocuments(const string &raw_query, FuncPredict predict) 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.         sort(matched_documents.begin(), matched_documents.end(),
  74.            
  75.             [EPSILON](const Document &lhs, const Document &rhs){
  76.                 if(abs(lhs.relevance - rhs.relevance) < EPSILON)
  77.                     return lhs.rating > rhs.rating;
  78.                  else
  79.                     return lhs.relevance > rhs.relevance;                
  80.             }
  81.         );
  82.  
  83.         if(matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT)
  84.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  85.  
  86.         return matched_documents;
  87.     }
  88.     auto FindTopDocuments(const string &raw_query) const{
  89.        
  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{return document_count_;};
  97.     tuple<vector<string>, DocumentStatus> MatchDocument(const string &raw_query, int document_id) const{
  98.         vector<string> matched_words;
  99.  
  100.         for(const string &word : ParseQuery(raw_query).plus_words)
  101.             if(word_to_document_freqs_.count(word))
  102.                 if(word_to_document_freqs_.at(word).count(document_id))
  103.                     matched_words.push_back(word);
  104.  
  105.  
  106.         for(const string &word : ParseQuery(raw_query).minus_words)
  107.             if(word_to_document_freqs_.count(word))
  108.                 if(word_to_document_freqs_.at(word).count(document_id)){
  109.                     matched_words.clear();
  110.                     break;
  111.                 }
  112.         return{matched_words, document_ratings_.at(document_id).status};
  113.     };
  114. private:
  115.     struct Query{
  116.         set<string> plus_words;
  117.         set<string> minus_words;
  118.     };
  119.     struct Status{
  120.         int rating;
  121.         DocumentStatus status;
  122.     };
  123.     map<string, map<int, double>> word_to_document_freqs_;
  124.     set<string> stop_words_;
  125.     int document_count_ = 0;
  126.     map<int, Status> document_ratings_;
  127.  
  128.     vector<string> SplitIntoWordsNoStop(const string &text) const{
  129.         vector<string> words;
  130.  
  131.         for(const string &word : SplitIntoWords(text))
  132.             if(!(stop_words_.count(word) > 0))
  133.                 words.push_back(word);
  134.         return words;
  135.     }
  136.     Query ParseQueryWord(const set<string> &text) const{
  137.         Query query;
  138.  
  139.         for(auto &word : text){
  140.             if(word[0] == '-'){
  141.                 query.minus_words.insert(word.substr(1));
  142.             } else
  143.                 query.plus_words.insert(word);
  144.         }
  145.         return query;
  146.     }
  147.     Query ParseQuery(const string &text) const{
  148.         set<string> query_words;
  149.  
  150.         for(const string &word : SplitIntoWordsNoStop(text))
  151.             query_words.insert(word);
  152.  
  153.         return ParseQueryWord(query_words);
  154.     }
  155.     template<typename FuncPredict>
  156.     vector<Document> FindAllDocuments(const Query &query_words, FuncPredict predict)const{
  157.         vector<Document> matched_documents;
  158.         map<int, double> document_to_relevance;
  159.  
  160.         for(const auto &query_word : query_words.plus_words)
  161.             if(word_to_document_freqs_.count(query_word))
  162.                 for(const auto &doc : word_to_document_freqs_.at(query_word))                      
  163.                     if(predict(doc.first,document_ratings_.at(doc.first).status,document_ratings_.at(doc.second).rating))
  164.                         document_to_relevance[doc.first] += log(document_count_ / (double)word_to_document_freqs_.at(query_word).size()) * doc.second;
  165.        
  166.         for(const auto &query_word : query_words.minus_words)
  167.             if(word_to_document_freqs_.count(query_word))
  168.                 for(const auto &doc : word_to_document_freqs_.at(query_word))
  169.                     document_to_relevance.erase(doc.first);
  170.  
  171.         for(const auto &[document_id, relevance] : document_to_relevance)
  172.             matched_documents.push_back({document_id,relevance,document_ratings_.at(document_id).rating});
  173.  
  174.         return matched_documents;
  175.  
  176.     }
  177.     static int ComputeAverageRating(const vector<int> &ratings){
  178.         int sum = 0;
  179.         if(ratings.size() == 0){
  180.             return 0;
  181.         } else{
  182.             for(const int &number : ratings)
  183.                 sum += number;
  184.             return sum / (int)ratings.size();
  185.         }
  186.         return 0;
  187.     }
  188. };
  189. void PrintDocument(const Document &document){
  190.     cout << "{ "s
  191.         << "document_id = "s << document.id << ", "s
  192.         << "relevance = "s << document.relevance << ", "s
  193.         << "rating = "s << document.rating
  194.         << " }"s << endl;
  195. }
  196. int main(){
  197.     SearchServer search_server;
  198.     search_server.SetStopWords("и в на"s);
  199.     search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, {8, -3});
  200.     search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, {7, 2, 7});
  201.     search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1});
  202.     search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, {9});
  203.     cout << "ACTUAL by default:"s << endl;
  204.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s)){
  205.         PrintDocument(document);
  206.     }
  207.     cout << "ACTUAL:"s << endl;
  208.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating){ return status == DocumentStatus::ACTUAL; })){
  209.         PrintDocument(document);
  210.     }
  211.     cout << "Even ids:"s << endl;
  212.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating){ return document_id % 2 == 0; })){
  213.         PrintDocument(document);
  214.     }
  215.     return 0;
  216. }
Advertisement
Add Comment
Please, Sign In to add comment