shizaero

Error_funct

Jan 15th, 2023 (edited)
163
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.22 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. const int EPSILON = 1e-6;
  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. }
  38. else {
  39. word += c;
  40. }
  41. }
  42. if (!word.empty()) {
  43. words.push_back(word);
  44. }
  45.  
  46. return words;
  47. }
  48.  
  49. struct Document {
  50. int id;
  51. double relevance;
  52. int rating;
  53. };
  54.  
  55. enum class DocumentStatus {
  56. ACTUAL,
  57. IRRELEVANT,
  58. BANNED,
  59. REMOVED,
  60. };
  61.  
  62. class SearchServer {
  63. public:
  64. void SetStopWords(const string& text) {
  65. for (const string& word : SplitIntoWords(text)) {
  66. stop_words_.insert(word);
  67. }
  68. }
  69.  
  70. void AddDocument(int document_id, const string& document, DocumentStatus status,
  71. const vector<int>& ratings) {
  72. const vector<string> words = SplitIntoWordsNoStop(document);
  73. const double inv_word_count = 1.0 / words.size();
  74. for (const string& word : words) {
  75. word_to_document_freqs_[word][document_id] += inv_word_count;
  76. }
  77. documents_.emplace(document_id, DocumentData{ ComputeAverageRating(ratings), status });
  78. }
  79.  
  80. template <typename Function>
  81. vector<Document> FindTopDocuments(const string& raw_query,
  82. Function funct) const {
  83. const Query query = ParseQuery(raw_query);
  84. auto matched_documents = FindAllDocuments(query, funct);
  85.  
  86. sort(matched_documents.begin(), matched_documents.end(),
  87. [](const Document& lhs, const Document& rhs) {
  88. if (abs(lhs.relevance - rhs.relevance) < EPSILON) {
  89. return lhs.rating > rhs.rating;
  90. }
  91. else {
  92. return lhs.relevance > rhs.relevance;
  93. }
  94. });
  95. if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  96. matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  97. }
  98. return matched_documents;
  99. }
  100.  
  101. /*
  102. vector<Document> FindTopDocuments(const string& raw_query) const {
  103. return FindTopDocuments(raw_query,
  104. [](int id, DocumentStatus status, int rating) {
  105. return status == DocumentStatus::ACTUAL;
  106. });
  107. }*/
  108.  
  109. vector<Document> FindTopDocuments(const string& raw_query, DocumentStatus status = DocumentStatus::ACTUAL) const {
  110. return FindTopDocuments(raw_query,
  111. [&status](int id, DocumentStatus status_doc, int rating) {
  112. return status_doc == status;
  113. });
  114. }
  115.  
  116. int GetDocumentCount() const {
  117. return documents_.size();
  118. }
  119.  
  120. tuple<vector<string>, DocumentStatus> MatchDocument(const string& raw_query,
  121. int document_id) const {
  122. const Query query = ParseQuery(raw_query);
  123. vector<string> matched_words;
  124. for (const string& word : query.plus_words) {
  125. if (word_to_document_freqs_.count(word) == 0) {
  126. continue;
  127. }
  128. if (word_to_document_freqs_.at(word).count(document_id)) {
  129. matched_words.push_back(word);
  130. }
  131. }
  132. for (const string& word : query.minus_words) {
  133. if (word_to_document_freqs_.count(word) == 0) {
  134. continue;
  135. }
  136. if (word_to_document_freqs_.at(word).count(document_id)) {
  137. matched_words.clear();
  138. break;
  139. }
  140. }
  141. return { matched_words, documents_.at(document_id).status };
  142. }
  143.  
  144. private:
  145. struct DocumentData {
  146. int rating;
  147. DocumentStatus status;
  148. };
  149.  
  150. set<string> stop_words_;
  151. map<string, map<int, double>> word_to_document_freqs_;
  152. map<int, DocumentData> documents_;
  153.  
  154. bool IsStopWord(const string& word) const {
  155. return stop_words_.count(word) > 0;
  156. }
  157.  
  158. vector<string> SplitIntoWordsNoStop(const string& text) const {
  159. vector<string> words;
  160. for (const string& word : SplitIntoWords(text)) {
  161. if (!IsStopWord(word)) {
  162. words.push_back(word);
  163. }
  164. }
  165. return words;
  166. }
  167.  
  168. static int ComputeAverageRating(const vector<int>& ratings) {
  169. if (ratings.empty()) {
  170. return 0;
  171. }
  172. int rating_sum = 0;
  173. for (const int rating : ratings) {
  174. rating_sum += rating;
  175. }
  176. return rating_sum / static_cast<int>(ratings.size());
  177. }
  178.  
  179. struct QueryWord {
  180. string data;
  181. bool is_minus;
  182. bool is_stop;
  183. };
  184.  
  185. QueryWord ParseQueryWord(string text) const {
  186. bool is_minus = false;
  187. // Word shouldn't be empty
  188. if (text[0] == '-') {
  189. is_minus = true;
  190. text = text.substr(1);
  191. }
  192. return { text, is_minus, IsStopWord(text) };
  193. }
  194.  
  195. struct Query {
  196. set<string> plus_words;
  197. set<string> minus_words;
  198. };
  199.  
  200. Query ParseQuery(const string& text) const {
  201. Query query;
  202. for (const string& word : SplitIntoWords(text)) {
  203. const QueryWord query_word = ParseQueryWord(word);
  204. if (!query_word.is_stop) {
  205. if (query_word.is_minus) {
  206. query.minus_words.insert(query_word.data);
  207. }
  208. else {
  209. query.plus_words.insert(query_word.data);
  210. }
  211. }
  212. }
  213. return query;
  214. }
  215.  
  216. // Existence required
  217. double ComputeWordInverseDocumentFreq(const string& word) const {
  218. return log(GetDocumentCount() * 1.0 / word_to_document_freqs_.at(word).size());
  219. }
  220. template <typename Function>
  221. vector<Document> FindAllDocuments(const Query& query, Function funct) const {
  222. map<int, double> document_to_relevance;
  223. for (const string& word : query.plus_words) {
  224. if (word_to_document_freqs_.count(word) == 0) {
  225. continue;
  226. }
  227. const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  228. for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  229. const auto& document = documents_.at(document_id);
  230. if (funct(document_id, document.status, document.rating)) {
  231. document_to_relevance[document_id] += term_freq * inverse_document_freq;
  232. }
  233. }
  234. }
  235.  
  236. for (const string& word : query.minus_words) {
  237. if (word_to_document_freqs_.count(word) == 0) {
  238. continue;
  239. }
  240. for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  241. document_to_relevance.erase(document_id);
  242. }
  243. }
  244.  
  245. vector<Document> matched_documents;
  246. for (const auto [document_id, relevance] : document_to_relevance) {
  247. matched_documents.push_back(
  248. { document_id, relevance, documents_.at(document_id).rating });
  249. }
  250. return matched_documents;
  251. }
  252. };
  253.  
  254. // ==================== для примера =========================
  255.  
  256. void PrintDocument(const Document& document) {
  257. cout << "{ "s
  258. << "document_id = "s << document.id << ", "s
  259. << "relevance = "s << document.relevance << ", "s
  260. << "rating = "s << document.rating
  261. << " }"s << endl;
  262. }
  263. int main() {
  264. SearchServer search_server;
  265. search_server.SetStopWords("и в на"s);
  266. search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, { 8, -3 });
  267. search_server.AddDocument(1, "пушистый кот пушистый хвост"s, DocumentStatus::ACTUAL, { 7, 2, 7 });
  268. search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, { 5, -12, 2, 1 });
  269. search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, { 9 });
  270. cout << "ACTUAL by default:"s << endl;
  271. for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s)) {
  272. PrintDocument(document);
  273. }
  274. cout << "ACTUAL:"s << endl;
  275. for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating) { return status == DocumentStatus::ACTUAL; })) {
  276. PrintDocument(document);
  277. }
  278. cout << "Even ids:"s << endl;
  279. for (const Document& document : search_server.FindTopDocuments("пушистый ухоженный кот"s, [](int document_id, DocumentStatus status, int rating) { return document_id % 2 == 0; })) {
  280. PrintDocument(document);
  281. }
  282. return 0;
  283. }
Advertisement
Add Comment
Please, Sign In to add comment