nochnoikoshmar1

Untitled

Mar 3rd, 2023
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 8.56 KB | Software | 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.     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;
  73.         if constexpr(is_same_v<FuncPredict, DocumentStatus>){
  74.             matched_documents = FindAllDocuments(query_words, predict);
  75.         }else{
  76.             matched_documents = FindAllDocuments(query_words, DocumentStatus::BANNED);
  77.         }
  78.         sort(matched_documents.begin(), matched_documents.end(),
  79.            
  80.             [EPSILON](const Document &lhs, const Document &rhs){
  81.                 if(abs(lhs.relevance - rhs.relevance) < EPSILON)
  82.                     return lhs.rating > rhs.rating;
  83.                  else
  84.                     return lhs.relevance > rhs.relevance;                
  85.             }
  86.         );
  87.         if(matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT){
  88.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  89.         }
  90.         return matched_documents;
  91.     }
  92.     vector<Document> FindTopDocuments(const string &raw_query, DocumentStatus status = DocumentStatus::ACTUAL) const{
  93.         return FindTopDocuments(raw_query,status);
  94.     }
  95.     auto FindTopDocuments(const string &raw_query) const{        
  96.         return FindTopDocuments(raw_query,
  97.             [](int document_id, DocumentStatus status, int rating){
  98.                 return status == DocumentStatus::ACTUAL;
  99.             }
  100.         );
  101.     }
  102.     int GetDocumentCount() const{return document_count_;};
  103.     tuple<vector<string>, DocumentStatus> MatchDocument(const string &raw_query, int document_id) const{
  104.         vector<string> matched_words;
  105.  
  106.         for(const string &word : ParseQuery(raw_query).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 : ParseQuery(raw_query).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.     struct Query{
  122.         set<string> plus_words;
  123.         set<string> minus_words;
  124.     };
  125.     struct Status{
  126.         int rating;
  127.         DocumentStatus status;
  128.     };
  129.     map<string, map<int, double>> word_to_document_freqs_;
  130.     set<string> stop_words_;
  131.     int document_count_ = 0;
  132.     map<int, Status> document_ratings_;
  133.  
  134.     vector<string> SplitIntoWordsNoStop(const string &text) const{
  135.         vector<string> words;
  136.  
  137.         for(const string &word : SplitIntoWords(text)){
  138.             if(!(stop_words_.count(word) > 0)){
  139.                 words.push_back(word);
  140.             }
  141.         }
  142.         return words;
  143.     }
  144.     Query ParseQueryWord(const set<string> &text) const{
  145.         Query query;
  146.  
  147.         for(auto &word : text){
  148.             if(word[0] == '-'){
  149.                 query.minus_words.insert(word.substr(1));
  150.             } else{
  151.                 query.plus_words.insert(word);
  152.             }
  153.         }
  154.         return query;
  155.     }
  156.     Query ParseQuery(const string &text) const{
  157.         set<string> query_words;
  158.  
  159.         for(const string &word : SplitIntoWordsNoStop(text)){
  160.             query_words.insert(word);
  161.         }
  162.         return ParseQueryWord(query_words);
  163.     }
  164.     template<typename FuncPredict>
  165.     vector<Document> FindAllDocuments(const Query &query_words, FuncPredict predict)const{
  166.         vector<Document> matched_documents;
  167.         map<int, double> document_to_relevance;
  168.  
  169.         for(const auto &query_word : query_words.plus_words){
  170.             if(word_to_document_freqs_.count(query_word)){
  171.                 for(const auto &[id,tf] : word_to_document_freqs_.at(query_word)){
  172.                     if(predict(id, document_ratings_.at(id).status, document_ratings_.at(id).rating)){
  173.                         document_to_relevance[id] += log(document_count_ / (double)word_to_document_freqs_.at(query_word).size()) * tf;
  174.                     }
  175.                 }
  176.             }
  177.         }
  178.         for(const auto &query_word : query_words.minus_words){
  179.             if(word_to_document_freqs_.count(query_word)){
  180.                 for(const auto &[id, tf] : word_to_document_freqs_.at(query_word)){
  181.                     document_to_relevance.erase(id);
  182.                 }
  183.             }
  184.         }
  185.         for(const auto &[document_id, relevance] : document_to_relevance){
  186.             matched_documents.push_back({document_id,relevance,document_ratings_.at(document_id).rating});
  187.         }
  188.         return matched_documents;
  189.     }
  190.     static int ComputeAverageRating(const vector<int> &ratings){
  191.         int sum = 0;
  192.         if(ratings.size() == 0){
  193.             return 0;
  194.         } else{
  195.             for(const int &number : ratings)
  196.                 sum += number;
  197.             return sum / (int)ratings.size();
  198.         }
  199.         return 0;
  200.     }
  201. };
  202. void PrintDocument(const Document &document){
  203.     cout << "{ "s
  204.         << "document_id = "s << document.id << ", "s
  205.         << "relevance = "s << document.relevance << ", "s
  206.         << "rating = "s << document.rating
  207.         << " }"s << endl;
  208. }
  209. int main() {
  210.     SearchServer search_server;
  211.     search_server.SetStopWords("и в на"s);
  212.     search_server.AddDocument(0, "белый кот и модный ошейник"s,        DocumentStatus::ACTUAL, {8, -3});
  213.     search_server.AddDocument(1, "пушистый кот пушистый хвост"s,       DocumentStatus::ACTUAL, {7, 2, 7});
  214.     search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1});
  215.     search_server.AddDocument(3, "ухоженный скворец евгений"s,         DocumentStatus::BANNED, {9});
  216.     cout << "ACTUAL by default:"s << endl;
  217.     for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s)) {
  218.         PrintDocument(document);
  219.     }
  220.     cout << "BANNED:"s << endl;
  221.     for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::BANNED)) {
  222.         PrintDocument(document);
  223.    }
  224.     cout << "Even ids:"s << endl;
  225.     for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating) { return document_id % 2 == 0; })) {
  226.         PrintDocument(document);
  227.     }
  228.     return 0;
  229. }
Advertisement
Add Comment
Please, Sign In to add comment