Advertisement
kutuzzzov

Урок 7. Перечислимые типы

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