shizaero

Рейтинг_авторское решение

Dec 5th, 2022
127
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.77 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.  
  13. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  14.  
  15. string ReadLine() {
  16.     string s;
  17.     getline(cin, s);
  18.     return s;
  19. }
  20.  
  21. int ReadLineWithNumber() {
  22.     int result;
  23.     cin >> result;
  24.     ReadLine();
  25.     return result;
  26. }
  27.  
  28. vector<string> SplitIntoWords(const string& text) {
  29.     vector<string> words;
  30.     string word;
  31.     for (const char c : text) {
  32.         if (c == ' ') {
  33.             if (!word.empty()) {
  34.                 words.push_back(word);
  35.                 word.clear();
  36.             }
  37.         } else {
  38.             word += c;
  39.         }
  40.     }
  41.     if (!word.empty()) {
  42.         words.push_back(word);
  43.     }
  44.  
  45.     return words;
  46. }
  47.    
  48. struct Document {
  49.     int id;
  50.     double relevance;
  51.     int rating;
  52. };
  53.    
  54. int ComputeAverageRating(const vector<int>& ratings) {
  55.     if (ratings.empty()) {
  56.         return 0;
  57.     }
  58.     int rating_sum = 0;
  59.     for (const int rating : ratings) {
  60.         rating_sum += rating;
  61.     }
  62.     // static_cast позволяет привести значение к типу int
  63.     // без использования дополнительной переменной
  64.     return rating_sum / static_cast<int>(ratings.size());
  65. }
  66.  
  67. class SearchServer {
  68. public:
  69.     void SetStopWords(const string& text) {
  70.         for (const string& word : SplitIntoWords(text)) {
  71.             stop_words_.insert(word);
  72.         }
  73.     }    
  74.    
  75.     void AddDocument(int document_id, const string& document, const vector<int>& ratings) {
  76.         const vector<string> words = SplitIntoWordsNoStop(document);
  77.         const double inv_word_count = 1.0 / words.size();
  78.         for (const string& word : words) {
  79.             word_to_document_freqs_[word][document_id] += inv_word_count;
  80.         }
  81.         document_ratings_.emplace(document_id, ComputeAverageRating(ratings));
  82.     }
  83.  
  84.     vector<Document> FindTopDocuments(const string& raw_query) const {            
  85.         const Query query = ParseQuery(raw_query);
  86.         auto matched_documents = FindAllDocuments(query);
  87.        
  88.         sort(matched_documents.begin(), matched_documents.end(),
  89.              [](const Document& lhs, const Document& rhs) {
  90.                  return lhs.relevance > rhs.relevance;
  91.              });
  92.         if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  93.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  94.         }
  95.         return matched_documents;
  96.     }
  97.    
  98. private:
  99.     set<string> stop_words_;
  100.     map<string, map<int, double>> word_to_document_freqs_;
  101.     map<int, int> document_ratings_;
  102.    
  103.     bool IsStopWord(const string& word) const {
  104.         return stop_words_.count(word) > 0;
  105.     }
  106.    
  107.     vector<string> SplitIntoWordsNoStop(const string& text) const {
  108.         vector<string> words;
  109.         for (const string& word : SplitIntoWords(text)) {
  110.             if (!IsStopWord(word)) {
  111.                 words.push_back(word);
  112.             }
  113.         }
  114.         return words;
  115.     }
  116.    
  117.     struct QueryWord {
  118.         string data;
  119.         bool is_minus;
  120.         bool is_stop;
  121.     };
  122.    
  123.     QueryWord ParseQueryWord(string text) const {
  124.         bool is_minus = false;
  125.         // Word shouldn't be empty
  126.         if (text[0] == '-') {
  127.             is_minus = true;
  128.             text = text.substr(1);
  129.         }
  130.         return {
  131.             text,
  132.             is_minus,
  133.             IsStopWord(text)
  134.         };
  135.     }
  136.    
  137.     struct Query {
  138.         set<string> plus_words;
  139.         set<string> minus_words;
  140.     };
  141.    
  142.     Query ParseQuery(const string& text) const {
  143.         Query query;
  144.         for (const string& word : SplitIntoWords(text)) {
  145.             const QueryWord query_word = ParseQueryWord(word);
  146.             if (!query_word.is_stop) {
  147.                 if (query_word.is_minus) {
  148.                     query.minus_words.insert(query_word.data);
  149.                 } else {
  150.                     query.plus_words.insert(query_word.data);
  151.                 }
  152.             }
  153.         }
  154.         return query;
  155.     }
  156.    
  157.     // Existence required
  158.     double ComputeWordInverseDocumentFreq(const string& word) const {
  159.         return log(document_ratings_.size() * 1.0 / word_to_document_freqs_.at(word).size());
  160.     }
  161.  
  162.     vector<Document> FindAllDocuments(const Query& query) const {
  163.         map<int, double> document_to_relevance;
  164.         for (const string& word : query.plus_words) {
  165.             if (word_to_document_freqs_.count(word) == 0) {
  166.                 continue;
  167.             }
  168.             const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  169.             for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  170.                 document_to_relevance[document_id] += term_freq * inverse_document_freq;
  171.             }
  172.         }
  173.        
  174.         for (const string& word : query.minus_words) {
  175.             if (word_to_document_freqs_.count(word) == 0) {
  176.                 continue;
  177.             }
  178.             for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  179.                 document_to_relevance.erase(document_id);
  180.             }
  181.         }
  182.  
  183.         vector<Document> matched_documents;
  184.         for (const auto [document_id, relevance] : document_to_relevance) {
  185.             matched_documents.push_back({
  186.                 document_id,
  187.                 relevance,
  188.                 document_ratings_.at(document_id)
  189.             });
  190.         }
  191.         return matched_documents;
  192.     }
  193. };
  194.  
  195.  
  196. SearchServer CreateSearchServer() {
  197.     SearchServer search_server;
  198.     search_server.SetStopWords(ReadLine());
  199.  
  200.     const int document_count = ReadLineWithNumber();
  201.     for (int document_id = 0; document_id < document_count; ++document_id) {
  202.         const string document = ReadLine();
  203.         int ratings_size;
  204.         cin >> ratings_size;
  205.        
  206.         // создали вектор размера ratings_size из нулей
  207.         vector<int> ratings(ratings_size, 0);
  208.        
  209.         // считали каждый элемент с помощью ссылки
  210.         for (int& rating : ratings) {
  211.             cin >> rating;
  212.         }
  213.        
  214.         search_server.AddDocument(document_id, document, ratings);
  215.         ReadLine();
  216.     }
  217.    
  218.     return search_server;
  219. }
  220.  
  221.  
  222. int main() {
  223.     const SearchServer search_server = CreateSearchServer();
  224.  
  225.     const string query = ReadLine();
  226.     for (const Document& document : search_server.FindTopDocuments(query)) {
  227.         cout << "{ "
  228.              << "document_id = " << document.id << ", "
  229.              << "relevance = " << document.relevance << ", "
  230.              << "rating = " << document.rating
  231.              << " }" << endl;
  232.     }
  233. }
Add Comment
Please, Sign In to add comment