Advertisement
VinnRonn

tuple

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