#include #include #include #include #include #include #include #include #include <> using namespace std; const int MAX_RESULT_DOCUMENT_COUNT = 5; string ReadLine() { string s; getline(cin, s); return s; } int ReadLineWithNumber() { int result; cin >> result; ReadLine(); return result; } vector SplitIntoWords(const string& text) { vector words; string word; for (const char c : text) { if (c == ' ') { words.push_back(word); word = ""; } else { word += c; } } words.push_back(word); return words; } enum class DocumentStatus { ACTUAL, IRRELEVANT, BANNED, REMOVED }; struct Document { int id; double relevance; int rating; DocumentStatus status; }; class SearchServer { public: void SetStopWords(const string& text) { for (const string& word : SplitIntoWords(text)) { stop_words_.insert(word); } } void AddDocument(int document_id, const string& document, DocumentStatus status, const vector& ratings) { const vector words = SplitIntoWordsNoStop(document); const double inv_word_count = 1.0 / words.size(); for (const string& word : words) { word_to_document_freqs_[word][document_id] += inv_word_count; } document_ratings_.insert({document_id, {ComputeAverageRating(ratings), status}}); } vector FindTopDocuments(const string& raw_query, DocumentStatus status) const { const Query query = ParseQuery(raw_query); auto matched_documents = FindAllDocuments(query, status); // for (auto doc : matched_documents) { // if (/* condition */) { // /* code */ // } // } sort(matched_documents.begin(), matched_documents.end(), [](const Document& lhs, const Document& rhs) { return lhs.relevance > rhs.relevance; }); if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) { matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT); } return matched_documents; } private: set stop_words_; map> word_to_document_freqs_; struct DocumentData { int rating; DocumentStatus status; }; map document_ratings_; bool IsStopWord(const string& word) const { return stop_words_.count(word) > 0; } vector SplitIntoWordsNoStop(const string& text) const { vector words; for (const string& word : SplitIntoWords(text)) { if (!IsStopWord(word)) { words.push_back(word); } } return words; } static int ComputeAverageRating(const vector& ratings) { int rating_sum = 0; for (const int rating : ratings) { rating_sum += rating; } return rating_sum / static_cast(ratings.size()); } struct QueryWord { string data; bool is_minus; bool is_stop; }; QueryWord ParseQueryWord(string text) const { bool is_minus = false; // Word shouldn't be empty if (text[0] == '-') { is_minus = true; text = text.substr(1); } return { text, is_minus, IsStopWord(text) }; } struct Query { set plus_words; set minus_words; }; Query ParseQuery(const string& text) const { Query query; for (const string& word : SplitIntoWords(text)) { const QueryWord query_word = ParseQueryWord(word); if (!query_word.is_stop) { if (query_word.is_minus) { query.minus_words.insert(query_word.data); } else { query.plus_words.insert(query_word.data); } } } return query; } // Existence required double ComputeWordInverseDocumentFreq(const string& word) const { return log(document_ratings_.size() * 1.0 / word_to_document_freqs_.at(word).size()); } vector FindAllDocuments(const Query& query, DocumentStatus status) const { map document_to_relevance; for (const string& word : query.plus_words) { if (word_to_document_freqs_.count(word) == 0) { continue; } const double inverse_document_freq = ComputeWordInverseDocumentFreq(word); for (const auto &[document_id, term_freq] : word_to_document_freqs_.at(word)) { document_to_relevance[document_id] += term_freq * inverse_document_freq; } } for (const string& word : query.minus_words) { if (word_to_document_freqs_.count(word) == 0) { continue; } for (const auto &[document_id, _] : word_to_document_freqs_.at(word)) { document_to_relevance.erase(document_id); } } vector matched_documents; for (const auto &[document_id, relevance] : document_to_relevance) { matched_documents.push_back({ document_id, relevance, document_ratings_.at(document_id), status }); } return matched_documents; } }; // SearchServer CreateSearchServer() { // SearchServer search_server; // search_server.SetStopWords(ReadLine()); // const int document_count = ReadLineWithNumber(); // for (int document_id = 0; document_id < document_count; ++document_id) { // const string document = ReadLine(); // int ratings_size; // cin >> ratings_size; // // создали вектор размера ratings_size из нулей // vector ratings(ratings_size, 0); // // считали каждый элемент с помощью ссылки // for (int& rating : ratings) { // cin >> rating; // } // search_server.AddDocument(document_id, document, ratings); // ReadLine(); // } // return search_server; // } void PrintDocument(const Document& document) { cout << "{ "s << "document_id = "s << document.id << ", "s << "relevance = "s << document.relevance << ", "s << "rating = "s << document.rating << " }"s << endl; } int main() { SearchServer search_server; search_server.SetStopWords("и в на"s); search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, {8, -3}); search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, {7, 2, 7}); search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, {5, -12, 2, 1}); search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, {9}); cout << "ACTUAL:"s << endl; for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::ACTUAL)) { PrintDocument(document); } cout << "BANNED:"s << endl; for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, DocumentStatus::BANNED)) { PrintDocument(document); } return 0; }