nochnoikoshmar1

Untitled

Mar 3rd, 2023
103
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 11.05 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.     vector<Document> 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.  
  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.     auto FindTopDocuments(const string &raw_query) 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.         }
  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.     static int ComputeAverageRating(const vector<int> &ratings){
  202.         int sum = 0;
  203.         if(ratings.size() == 0){
  204.             return 0;
  205.         } else{
  206.             for(const int &number : ratings)
  207.                 sum += number;
  208.             return sum / (int)ratings.size();
  209.         }
  210.         return 0;
  211.     }
  212. };
  213. void PrintDocument(const Document &document){
  214.     cout << "{ "s
  215.         << "document_id = "s << document.id << ", "s
  216.         << "relevance = "s << document.relevance << ", "s
  217.         << "rating = "s << document.rating
  218.         << " }"s << endl;
  219. }
  220. int main(){
  221.     SearchServer search_server;
  222.     search_server.SetStopWords("и в на"s);
  223.     search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, {8, -3});
  224.     search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, {7, 2, 7});
  225.     search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1});
  226.     search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, {9});
  227.     cout << "ACTUAL by default:"s << endl;
  228.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s)){
  229.         PrintDocument(document);
  230.     }
  231.     cout << "BANNED:"s << endl;
  232.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::BANNED)){
  233.         PrintDocument(document);
  234.     }
  235.     cout << "Even ids:"s << endl;
  236.     for(const Document &document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating){ return document_id % 2 == 0; })){
  237.         PrintDocument(document);
  238.     }
  239.     return 0;
  240. }
  241. /*enum class AnimalSortKey{
  242.     AGE,     // по полю age
  243.     WEIGHT,  // по полю weight
  244.     RELATIVE_WEIGHT  // по weight / age
  245. };
  246. struct Animal{
  247.     string name;
  248.     int age;
  249.     double weight;
  250. };
  251. template <typename Container, typename KeyMapper>
  252. void SortBy(Container &container, KeyMapper key_mapper, bool reverse = false){
  253.     if constexpr(is_same_v<KeyMapper, AnimalSortKey>){
  254.         switch(key_mapper){
  255.             case AnimalSortKey::AGE:
  256.                 return SortBy(container, [](const auto &x){ return x.age; }, reverse);
  257.             case AnimalSortKey::WEIGHT:
  258.                 return SortBy(container, [](const auto &x){ return x.weight; }, reverse);
  259.             case AnimalSortKey::RELATIVE_WEIGHT:
  260.                 return SortBy(container, [](const auto &x){ return x.weight / x.age; }, reverse);
  261.         }
  262.     } else{
  263.         if(reverse){
  264.             sort(container.begin(), container.end(),
  265.                 [key_mapper](const auto &lhs, const auto &rhs){
  266.                     return key_mapper(lhs) > key_mapper(rhs);
  267.                 }
  268.             );
  269.         } else{
  270.             sort(container.begin(), container.end(),
  271.                 [key_mapper](const auto &lhs, const auto &rhs){
  272.                     return key_mapper(lhs) < key_mapper(rhs);
  273.                 }
  274.             );
  275.         }
  276.     }
  277. }
  278. void PrintNames(const vector<Animal> &animals){
  279.     for(const Animal &animal : animals){
  280.         cout << animal.name << ' ';
  281.     }
  282.     cout << endl;
  283. }
  284. int main(){
  285.     setlocale(LC_ALL, "");
  286.     vector<Animal> animals = {
  287.         {"Мурка"s,   10, 5},
  288.         {"Белка"s,   5,  1.5},
  289.         {"Георгий"s, 2,  4.5},
  290.         {"Рюрик"s,   12, 3.1},
  291.     };
  292.     PrintNames(animals);
  293.     // Мурка Белка Георгий Рюрик
  294.     SortBy(animals, [](const Animal &animal){ return animal.name; }, true);
  295.     PrintNames(animals);
  296.     // Рюрик Мурка Георгий Белка
  297.     SortBy(animals, AnimalSortKey::RELATIVE_WEIGHT);
  298.     PrintNames(animals);
  299.     // ожидаем вывод: Рюрик Белка Мурка Георгий
  300. }*/
Advertisement
Add Comment
Please, Sign In to add comment