Advertisement
VinnRonn

return tuple

Jun 4th, 2022
29
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.69 KB | None | 0 0
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <set>
  4. #include <map>
  5. #include <string>
  6. #include <utility>
  7. #include <vector>
  8. #include <cmath>
  9. #include <numeric>
  10.  
  11. using namespace std;
  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 = 0;
  23. cin >> result;
  24. ReadLine();
  25. return result;
  26. }
  27.  
  28. // type of doc
  29. enum class DocumentStatus {
  30. ACTUAL,
  31. IRRELEVANT,
  32. BANNED,
  33. REMOVED
  34. };
  35.  
  36. vector<string> SplitIntoWords(const string& text) {
  37. vector<string> words;
  38. string word;
  39. for (const char c : text) {
  40. if (c == ' ') {
  41. if (!word.empty()) {
  42. words.push_back(word);
  43. word.clear();
  44. }
  45. }
  46. else {
  47. word += c;
  48. }
  49. }
  50. if (!word.empty()) {
  51. words.push_back(word);
  52. }
  53.  
  54. return words;
  55. }
  56.  
  57. struct Document {
  58. int id;
  59. double relevance;
  60. int rating;
  61. };
  62.  
  63. bool FindWord(const string& word, const map<string, set<int>>& word_to_documents, const int& id) {
  64. return word_to_documents.count(word) && word_to_documents.at(word).count(id);
  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, DocumentStatus status, const vector<int>& ratings) {
  76. const vector<string> words = SplitIntoWordsNoStop(document);
  77.  
  78. document_rating_[document_id] = ComputeAverageRating(ratings);
  79.  
  80. document_status_[document_id] = status;
  81.  
  82. double count_word = 0.0;
  83.  
  84. for (const auto& w : words) {
  85. count_word = count(words.begin(), words.end(), w);
  86.  
  87. word_to_documents_[w].insert(document_id);
  88. word_to_document_freqs_[w].insert({ document_id, count_word / words.size() });
  89. }
  90. ++documents_count_;
  91. }
  92.  
  93. vector<Document> FindTopDocuments(const string& raw_query, DocumentStatus status = DocumentStatus::ACTUAL) const {
  94.  
  95. const Query query_words = ParseQuery(raw_query);
  96. auto matched_documents = FindAllDocuments(query_words, status);
  97.  
  98.  
  99. sort(matched_documents.begin(), matched_documents.end(),
  100. [](const Document& lhs, const Document& rhs) {
  101. return lhs.relevance > rhs.relevance;
  102. });
  103.  
  104.  
  105.  
  106. if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  107. matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  108. }
  109. return matched_documents;
  110. }
  111.  
  112. static int ComputeAverageRating(const vector<int>& ratings) {
  113. if (ratings.empty()) {
  114. return 0;
  115. }
  116. int document_rating = accumulate(ratings.begin(), ratings.end(), 0);
  117. return document_rating / static_cast<int>(ratings.size());
  118. }
  119.  
  120. tuple<vector<string>, DocumentStatus> MatchDocument(const string& raw_query, int document_id) const {
  121.  
  122. //исключаю пустой запрос и кривой id
  123. if (raw_query.empty() || document_id > documents_count_) {
  124. return {};
  125. }
  126.  
  127. Query query;
  128. query = ParseQuery(raw_query);
  129.  
  130. for (const auto& minus : query.minus_words) {
  131. if (FindWord(minus, word_to_documents_, document_id)) {
  132. return {};
  133. }
  134. }
  135.  
  136. vector<string> words;
  137.  
  138. for (const auto& plus : query.plus_words) {
  139. if (FindWord(plus, word_to_documents_, document_id)) {
  140. words.push_back(plus);
  141. }
  142. }
  143.  
  144. sort(words.begin(), words.end());
  145.  
  146. return { words, document_status_.at(document_id) };
  147.  
  148. };
  149.  
  150. int GetDocumentCount() {
  151. return documents_count_;
  152. }
  153.  
  154. private:
  155.  
  156. struct Status { // почему не хранить статус в документе?
  157. int id;
  158. double rating;
  159. DocumentStatus status;
  160. };
  161.  
  162. struct Query {
  163.  
  164. set<string> plus_words;
  165. set<string> minus_words;
  166. };
  167.  
  168. map<string, set<int>> word_to_documents_;
  169. map<string, map<int, double>> word_to_document_freqs_;
  170.  
  171. set<string> stop_words_;
  172.  
  173. map<int, int> document_rating_;
  174. map<int, DocumentStatus> document_status_;
  175.  
  176. int documents_count_ = 0;
  177.  
  178. bool IsStopWord(const string& word) const {
  179. return stop_words_.count(word) > 0;
  180. }
  181.  
  182. vector<string> SplitIntoWordsNoStop(const string& text) const {
  183. vector<string> words;
  184. for (const string& word : SplitIntoWords(text)) {
  185. if (!IsStopWord(word))
  186. {
  187. words.push_back(word);
  188. }
  189. }
  190. return words;
  191. }
  192.  
  193. Query ParseQuery(const string& text) const {
  194. Query query;
  195. vector<string> raw_words = SplitIntoWordsNoStop(text);
  196.  
  197. for (const string& word : raw_words) {
  198. if (word[0] == '-')
  199. {
  200. query.minus_words.insert(word.substr(1));
  201. }
  202. }
  203. for (const string& min : raw_words) {
  204. if (min[0] != '-' && !query.minus_words.count(min))
  205. {
  206. query.plus_words.insert(min);
  207. }
  208. }
  209. return query;
  210. }
  211.  
  212.  
  213. // IDF-TF
  214.  
  215. vector<Document> FindAllDocuments(const Query& query_words, DocumentStatus status = DocumentStatus::ACTUAL) const {
  216. vector<Document> matched_documents;
  217. map<int, double> document_to_relevance;
  218.  
  219. double IDF = 0.0;
  220.  
  221. //вынести в отдельную функцию учет plus слов
  222.  
  223. for (const auto& plus : query_words.plus_words) {
  224.  
  225. if (word_to_documents_.count(plus))
  226. {
  227. IDF = log(static_cast<double>(documents_count_) / word_to_documents_.at(plus).size());
  228. //cout << word_to_documents_.at(plus).size() << endl << IDF << endl;
  229.  
  230. for (const auto& id : word_to_documents_.at(plus)) {
  231.  
  232. if (status == document_status_.at(id))
  233. {
  234. document_to_relevance[id] += IDF * word_to_document_freqs_.at(plus).at(id);
  235. }
  236.  
  237. //cout << IDF * (1.0 / documents_size_.at(id)) << endl;
  238.  
  239. };
  240. }
  241. }
  242.  
  243. //вынести в отдельную функцию учет minus слов
  244.  
  245. for (const auto& minus : query_words.minus_words) {
  246.  
  247. if (word_to_documents_.count(minus)) {
  248. for (const auto& id : word_to_documents_.at(minus)) {
  249. document_to_relevance.erase(id);
  250. };
  251. }
  252. }
  253.  
  254. for (const auto& [id, relevance] : document_to_relevance) {
  255. matched_documents.push_back({ id, relevance, document_rating_.at(id) });
  256. }
  257.  
  258. return matched_documents;
  259. }
  260.  
  261. };
  262. void PrintMatchDocumentResult(int document_id, const vector<string>& words, DocumentStatus status) {
  263. cout << "{ "s
  264. << "document_id = "s << document_id << ", "s
  265. << "status = "s << static_cast<int>(status) << ", "s
  266. << "words ="s;
  267. for (const string& word : words) {
  268. cout << ' ' << word;
  269. }
  270. cout << "}"s << endl;
  271. }
  272.  
  273. int main() {
  274. SearchServer search_server;
  275. search_server.SetStopWords("и в на"s);
  276.  
  277. search_server.AddDocument(0, "белый кот и модный ошейник"s, DocumentStatus::ACTUAL, { 8, -3 });
  278. //search_server.AddDocument(0, "белый кот и модный ошейник кот"s, DocumentStatus::ACTUAL, { 8, -3 });
  279. search_server.AddDocument(1, "пушистый кот пушистый хвост кот"s, DocumentStatus::ACTUAL, { 7, 2, 7 });
  280. search_server.AddDocument(2, "ухоженный пёс выразительные глаза"s, DocumentStatus::ACTUAL, { 5, -12, 2, 1 });
  281. search_server.AddDocument(3, "ухоженный скворец евгений"s, DocumentStatus::BANNED, { 9 });
  282.  
  283. const int document_count = search_server.GetDocumentCount();
  284. for (int document_id = 0; document_id < document_count; ++document_id) {
  285. const auto [words, status] = search_server.MatchDocument("пушистый кот"s, document_id);
  286. PrintMatchDocumentResult(document_id, words, status);
  287. }
  288. }
  289. /*
  290. * "пушистый кот -ошейник"
  291. * "пушистый -кот"
  292. * "пёс скворец -ухоженный"
  293. * "пушистый кот модный"
  294. * "-ухоженный"
  295. * "пёс скворец"
  296. * "шашлык автомобиль дом велосипед"
  297. * " "
  298. * ""
  299. */
  300.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement