Advertisement
RobertDeMilo

Возврат нескольких значений из функции

Oct 21st, 2023
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 9.16 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <map>
  5. #include <set>
  6. #include <string>
  7. #include <utility>
  8. #include <vector>
  9.  
  10. using namespace std;
  11.  
  12. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  13.  
  14. struct Document {
  15.     int id;
  16.     double relevance;
  17.     int rating;
  18. };
  19.  
  20. enum class DocumentStatus
  21. {
  22.     ACTUAL,
  23.     IRRELEVANT,
  24.     BANNED,
  25.     REMOVED
  26. };
  27.  
  28.  
  29. string ReadLine() {
  30.     string s;
  31.     getline(cin, s);
  32.     return s;
  33. }
  34.  
  35. int ReadLineWithNumber() {
  36.     int result;
  37.     cin >> result;
  38.     ReadLine();
  39.     return result;
  40. }
  41.  
  42. vector<string> SplitIntoWords(const string& text) {
  43.     vector<string> words;
  44.     string word;
  45.     for (const char c : text) {
  46.         if (c == ' ') {
  47.             words.push_back(word);
  48.             word = "";
  49.         }
  50.         else {
  51.             word += c;
  52.         }
  53.     }
  54.     words.push_back(word);
  55.  
  56.     return words;
  57. }
  58.  
  59. class SearchServer {
  60. public:
  61.     void SetStopWords(const string& text) {
  62.         for (const string& word : SplitIntoWords(text)) {
  63.             stop_words_.insert(word);
  64.         }
  65.     }
  66.  
  67.     void AddDocument(int document_id, const string& document, DocumentStatus status, const vector<int>& ratings) {
  68.         const vector<string> words = SplitIntoWordsNoStop(document);
  69.         const double inv_word_count = 1.0 / words.size();
  70.         for (const string& word : words) {
  71.             word_to_document_freqs_[word][document_id] += inv_word_count;
  72.         }
  73.         document_ratings_[document_id]= { ComputeAverageRating(ratings), status};
  74.  
  75.         //struct Doc
  76.         //{
  77.         //    int rating;
  78.         //    DocumentStatus status;
  79.         //};
  80.         //// id , {rat, status}
  81.         //map<int, Doc> document_ratings_;
  82.     }
  83.     int GetDocumentCount()
  84.     {
  85.         return static_cast<int>(document_ratings_.size());
  86.     }
  87.  
  88.     tuple<vector<string>, DocumentStatus> MatchDocument(const string& raw_query, int document_id) const
  89.     {
  90.         // Если документ не соответствует запросу(нет пересечений по плюс - словам или есть минус - слово), вектор слов нужно вернуть пустым.
  91.  
  92.         Query query = ParseQuery(raw_query);
  93.  
  94.  
  95.         vector<string> pluss_wordss;
  96.  
  97.         for (const string& word : query.plus_words)
  98.         {
  99.             if (word_to_document_freqs_.count(word) != 0 && word_to_document_freqs_.at(word).count(document_id) != 0)
  100.             {
  101.                 pluss_wordss.push_back(word);
  102.             }
  103.         }
  104.  
  105.         for (const string& word : query.minus_words)
  106.         {
  107.             if (word_to_document_freqs_.count(word) != 0 && word_to_document_freqs_.at(word).count(document_id) != 0)
  108.             {
  109.                 pluss_wordss.clear();
  110.                 break;
  111.             }
  112.         }
  113.  
  114.        // map<int, Doc> document_ratings_;
  115.         return { pluss_wordss, document_ratings_.at(document_id).status};
  116.     }
  117.  
  118.  
  119.  
  120.     vector<Document> FindTopDocuments(const string& raw_query, DocumentStatus statuss = DocumentStatus::ACTUAL) const {
  121.         const Query query = ParseQuery(raw_query);
  122.  
  123.         auto matched_documents2 = FindAllDocuments(query);
  124.  
  125.         vector<Document> matched_documents;
  126.        
  127.  
  128.             for (auto it = find_if(matched_documents2.begin(), matched_documents2.end(),
  129.                 [this, statuss](Document & document)
  130.                 {return (document_ratings_.count(document.id) != 0 && document_ratings_.at(document.id).status == statuss);}); it != matched_documents2.end();  
  131.                 it = find_if(next(it), matched_documents2.end(),
  132.                     [this, statuss](Document& document)
  133.                     {return (document_ratings_.count(document.id) != 0 && document_ratings_.at(document.id).status == statuss); }))
  134.             {
  135.                 matched_documents.push_back(*it);
  136.             }
  137.  
  138.      
  139.        
  140.  
  141.         sort(matched_documents.begin(), matched_documents.end(),
  142.             [](const Document& lhs, const Document& rhs) {
  143.                 return lhs.relevance > rhs.relevance;
  144.             });
  145.         if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  146.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  147.         }
  148.         return matched_documents;
  149.     }
  150.  
  151. private:
  152.     set<string> stop_words_;
  153.     map<string, map<int, double>> word_to_document_freqs_;
  154.  
  155.    
  156.  
  157.     struct Query {
  158.         set<string> plus_words;
  159.         set<string> minus_words;
  160.     };
  161.  
  162.     struct QueryWord {
  163.         string data;
  164.         bool is_minus;
  165.         bool is_stop;
  166.     };
  167.  
  168.     struct Doc
  169.     {
  170.         int rating;
  171.         DocumentStatus status;
  172.     };
  173.  
  174.     // id , {rat, status}
  175.     map<int, Doc> document_ratings_;
  176.  
  177.    
  178.  
  179.  
  180.     bool IsStopWord(const string& word) const {
  181.         return stop_words_.count(word) > 0;
  182.     }
  183.  
  184.     vector<string> SplitIntoWordsNoStop(const string& text) const {
  185.         vector<string> words;
  186.         for (const string& word : SplitIntoWords(text)) {
  187.             if (!IsStopWord(word)) {
  188.                 words.push_back(word);
  189.             }
  190.         }
  191.         return words;
  192.     }
  193.  
  194.     static int ComputeAverageRating(const vector<int>& ratings) {
  195.         int rating_sum = 0;
  196.         for (const int rating : ratings) {
  197.             rating_sum += rating;
  198.         }
  199.         return rating_sum / static_cast<int>(ratings.size());
  200.     }
  201.  
  202.    
  203.  
  204.     QueryWord ParseQueryWord(string text) const {
  205.         bool is_minus = false;
  206.         // Word shouldn't be empty
  207.         if (text[0] == '-') {
  208.             is_minus = true;
  209.             text = text.substr(1);
  210.         }
  211.         return {
  212.             text,
  213.             is_minus,
  214.             IsStopWord(text)
  215.         };
  216.     }
  217.  
  218.    
  219.  
  220.     Query ParseQuery(const string& text) const {
  221.         Query query;
  222.         for (const string& word : SplitIntoWords(text)) {
  223.             const QueryWord query_word = ParseQueryWord(word);
  224.             if (!query_word.is_stop) {
  225.                 if (query_word.is_minus) {
  226.                     query.minus_words.insert(query_word.data);
  227.                 }
  228.                 else {
  229.                     query.plus_words.insert(query_word.data);
  230.                 }
  231.             }
  232.         }
  233.         return query;
  234.     }
  235.  
  236.     // Existence required
  237.     double ComputeWordInverseDocumentFreq(const string& word) const {
  238.         return log(document_ratings_.size() * 1.0 / word_to_document_freqs_.at(word).size());
  239.     }
  240.  
  241.     vector<Document> FindAllDocuments(const Query& query) const {
  242.         map<int, double> document_to_relevance;
  243.         for (const string& word : query.plus_words) {
  244.             if (word_to_document_freqs_.count(word) == 0) {
  245.                 continue;
  246.             }
  247.             const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  248.             for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  249.                 document_to_relevance[document_id] += term_freq * inverse_document_freq;
  250.             }
  251.         }
  252.  
  253.         for (const string& word : query.minus_words) {
  254.             if (word_to_document_freqs_.count(word) == 0) {
  255.                 continue;
  256.             }
  257.             for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  258.                 document_to_relevance.erase(document_id);
  259.             }
  260.         }
  261.  
  262.         vector<Document> matched_documents;
  263.  
  264.         for (const auto [document_id, relevance] : document_to_relevance) {
  265.             matched_documents.push_back({
  266.                 document_id,
  267.                 relevance,
  268.                 document_ratings_.at(document_id).rating
  269.                 });
  270.         }
  271.         return matched_documents;
  272.     }
  273. };
  274.  
  275.  
  276. void PrintMatchDocumentResult(int document_id, const vector<string>& words, DocumentStatus status) {
  277.     cout << "{ "s
  278.         << "document_id = "s << document_id << ", "s
  279.         << "status = "s << static_cast<int>(status) << ", "s
  280.         << "words ="s;
  281.     for (const string& word : words) {
  282.         cout << ' ' << word;
  283.     }
  284.     cout << "}"s << endl;
  285. }
  286. int main() {
  287.     SearchServer search_server;
  288.     search_server.SetStopWords("и в на"s);
  289.     search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, { 8, -3 });
  290.     search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, { 7, 2, 7 });
  291.     search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, { 5, -12, 2, 1 });
  292.     search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, { 9 });
  293.  
  294.     const int document_count = search_server.GetDocumentCount();
  295.  
  296.     for (int document_id = 0; document_id < document_count; ++document_id)
  297.     {
  298.         const auto [words, status] = search_server.MatchDocument("пушистый кот"s, document_id);
  299.  
  300.         PrintMatchDocumentResult(document_id, words, status);
  301.     }
  302.  
  303.  
  304.     //{ document_id = 0, status = 0, words = кот}
  305.     //{ document_id = 1, status = 0, words = кот пушистый}
  306.     //{ document_id = 2, status = 0, words = }
  307.     //{ document_id = 3, status = 2, words = }
  308. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement