Advertisement
khaze1

cpp-search-server | rating

Oct 2nd, 2023
130
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.27 KB | None | 0 0
  1. #include <algorithm>
  2. #include <cmath>
  3. #include <iostream>
  4. #include <numeric>
  5. #include <map>
  6. #include <set>
  7. #include <string>
  8. #include <utility>
  9. #include <vector>
  10.  
  11. using namespace std;
  12.  
  13. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  14.  
  15. struct Document {
  16.     int id;
  17.     double relevance;
  18.     int rating;
  19. };
  20.  
  21. struct Query {
  22.     set<string> words_;
  23.     set<string> minus_words_;
  24. };
  25.  
  26. string ReadLine() {
  27.     string s;
  28.     getline(cin, s);
  29.     return s;
  30. }
  31.  
  32. int ReadLineWithNumber() {
  33.     int result = 0;
  34.     cin >> result;
  35.     ReadLine();
  36.     return result;
  37. }
  38.  
  39. vector<int> ReadRatings(){
  40.     int n;
  41.     cin >> n;
  42.     vector<int> ratings(n);
  43.     for (int i = 0; i < n; ++i){
  44.         cin >> ratings[i];
  45.     }
  46.     return ratings;
  47. }
  48.  
  49.  
  50. vector<int> ReadRatings2(){
  51.     vector<int> ratings(ReadLineWithNumber());
  52.     for (size_t i = 0; i < ratings.size(); ++i){
  53.         cin >> ratings[i];
  54.     }
  55.     return ratings;
  56. }
  57.  
  58. vector<string> SplitIntoWords(const string& text) {
  59.     vector<string> words;
  60.     string word;
  61.     for (const char c : text) {
  62.         if (c == ' ') {
  63.             if (!word.empty()) {
  64.                 words.push_back(word);
  65.                 word.clear();
  66.             }
  67.         } else {
  68.             word += c;
  69.         }
  70.     }
  71.     if (!word.empty()) {
  72.         words.push_back(word);
  73.     }
  74.  
  75.     return words;
  76. }
  77.  
  78. Query ParseQuery(const string& text) {
  79.     Query query;
  80.     string word;
  81.     bool minus_word = false;
  82.     for (const char c : text) {
  83.         if (c == ' ') {
  84.             if (!word.empty()) {
  85.                 if (minus_word){
  86.                     query.minus_words_.insert(word);
  87.                     minus_word = false;
  88.                 }
  89.                 else
  90.                     query.words_.insert(word);
  91.                 word.clear();
  92.             }
  93.         }
  94.         else if (c == '-') {
  95.             minus_word = true;
  96.         }
  97.         else {
  98.             word += c;
  99.         }
  100.     }
  101.     if (!word.empty()) {
  102.         if (minus_word)
  103.             query.minus_words_.insert(word);
  104.         else
  105.             query.words_.insert(word);
  106.     }
  107.  
  108.     return query;
  109.     }
  110.  
  111. int ComputeAverageRating(const vector<int>& ratings) {
  112.     return accumulate(ratings.begin(), ratings.end(), 0) / static_cast<int>(ratings.size());
  113. }
  114.  
  115.  
  116. class SearchServer {
  117. private:
  118.     struct DocumentContent {
  119.         int id = 0;
  120.         vector<string> words;
  121.         int rating;
  122.     };
  123.  
  124.     set<string> stop_words_;
  125.     vector<DocumentContent> documents_;
  126.     map<string, map<int, double>> word_to_document_freqs_;
  127.     map<int, int> ratings_;
  128.  
  129.     vector<string> SplitIntoWordsNoStop(const string& text) const {
  130.         vector<string> words;
  131.         for (const string& word : SplitIntoWords(text)) {
  132.             if (stop_words_.count(word) == 0) {
  133.                 words.push_back(word);
  134.             }
  135.         }
  136.         return words;
  137.     }
  138.  
  139.     double Compute_IDF(const string& word) const {
  140.         return log( static_cast<double>(documents_.size())
  141.             / static_cast<double>(word_to_document_freqs_.at(word).size()) );
  142.     }
  143.  
  144.     void ExcludeMinusWords(const Query& query, map<int, double>& docs_relevance) const {
  145.         for (const string& word : query.minus_words_){
  146.             if (word_to_document_freqs_.count(word)){
  147.                 for (const auto& [id, tf] : word_to_document_freqs_.at(word)){
  148.                     docs_relevance.erase(id);
  149.                 }
  150.             }
  151.         }
  152.     }
  153.    
  154.     vector<Document> FindAllMatchedDocuments(const Query& query) const {
  155.         map<int, double> docs_relevance;
  156.         vector<Document> matched_documents;
  157.         for (const string& word : query.words_){
  158.             if (word_to_document_freqs_.count(word)){
  159.                 const double idf = Compute_IDF(word);
  160.                 for (const auto& [id, tf] : word_to_document_freqs_.at(word)){
  161.                     docs_relevance[id] += idf * tf;
  162.                 }
  163.             }
  164.         }
  165.         ExcludeMinusWords(query, docs_relevance);
  166.         for (const auto& [id, relevance] : docs_relevance){
  167.             matched_documents.push_back({id, relevance, ratings_.at(id)});
  168.         }
  169.         return matched_documents;
  170.     }
  171.  
  172. public:
  173.    
  174.     void SetStopWords(const string& text){
  175.         for (const string& word : SplitIntoWords(text)) {
  176.             stop_words_.insert(word);
  177.         }
  178.     }
  179.    
  180.     void AddDocument(int document_id, const string& document, const vector<int>& ratings){
  181.         const vector<string> words = SplitIntoWordsNoStop(document);
  182.         int rating = ComputeAverageRating(ratings);
  183.         double tf = 1. / words.size();
  184.         for (const string& word : words){
  185.             word_to_document_freqs_[word][document_id] += tf;
  186.         }
  187.         ratings_[document_id] = rating;
  188.         documents_.push_back({document_id, words, rating});
  189.     }
  190.  
  191.     vector<Document> FindTopDocuments(const string& raw_query) const {
  192.         Query query = ParseQuery(raw_query);
  193.         vector<Document> matched_documents = FindAllMatchedDocuments(query);
  194.         sort(matched_documents.begin(), matched_documents.end(),
  195.                 [](const Document& ld, const Document& rd) {
  196.                     return ld.relevance > rd.relevance;
  197.                 }
  198.             );
  199.         if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  200.             matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  201.         }
  202.    
  203.         return matched_documents;
  204.     }
  205. };
  206.  
  207.  
  208. SearchServer CreateSearchServer(){
  209.     SearchServer search_server;
  210.     //cout << "Set stop words:" << endl;
  211.     search_server.SetStopWords(ReadLine());
  212.     //cout << "Set amoumt of documents:" << endl;
  213.     const int document_count = ReadLineWithNumber();
  214.     for (int document_id = 0; document_id < document_count; ++document_id) {
  215.         string words = ReadLine();
  216.         vector<int> ratings = ReadRatings();
  217.         search_server.AddDocument(document_id, words, ratings);
  218.     }
  219.     return search_server;
  220. }
  221.  
  222. int main() {
  223.  
  224.     const SearchServer search_server = CreateSearchServer();
  225.     for (auto [document_id, relevance, rating] : search_server.FindTopDocuments(ReadLine())) {
  226.         cout << "{ document_id = "s << document_id << ", relevance = "s << relevance
  227.              << ", rating = "s << rating << " }"s << endl;
  228.     }
  229.  
  230. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement