Advertisement
VinnRonn

RequestQueue

Aug 4th, 2022 (edited)
49
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.58 KB | None | 0 0
  1. // search_server_s3_t3_v3.cpp
  2.  
  3. #include <algorithm>
  4. #include <cmath>
  5. #include <iostream>
  6. #include <map>
  7. #include <set>
  8. #include <stdexcept>
  9. #include <string>
  10. #include <utility>
  11. #include <vector>
  12. #include <stack>
  13. #include <deque>
  14.  
  15. using namespace std;
  16.  
  17. const int MAX_RESULT_DOCUMENT_COUNT = 5;
  18.  
  19. string ReadLine() {
  20. string s;
  21. getline(cin, s);
  22. return s;
  23. }
  24.  
  25. int ReadLineWithNumber() {
  26. int result;
  27. cin >> result;
  28. ReadLine();
  29. return result;
  30. }
  31.  
  32. vector<string> SplitIntoWords(const string& text) {
  33. vector<string> words;
  34. string word;
  35. for (const char c : text) {
  36. if (c == ' ') {
  37. if (!word.empty()) {
  38. words.push_back(word);
  39. word.clear();
  40. }
  41. }
  42. else {
  43. word += c;
  44. }
  45. }
  46. if (!word.empty()) {
  47. words.push_back(word);
  48. }
  49.  
  50. return words;
  51. }
  52.  
  53. struct Document {
  54. Document() = default;
  55.  
  56. Document(int id, double relevance, int rating)
  57. : id(id)
  58. , relevance(relevance)
  59. , rating(rating) {
  60. }
  61.  
  62. int id = 0;
  63. double relevance = 0.0;
  64. int rating = 0;
  65. };
  66.  
  67. template <typename StringContainer>
  68. set<string> MakeUniqueNonEmptyStrings(const StringContainer& strings) {
  69. set<string> non_empty_strings;
  70. for (const string& str : strings) {
  71. if (!str.empty()) {
  72. non_empty_strings.insert(str);
  73. }
  74. }
  75. return non_empty_strings;
  76. }
  77.  
  78. enum class DocumentStatus {
  79. ACTUAL,
  80. IRRELEVANT,
  81. BANNED,
  82. REMOVED,
  83. };
  84.  
  85. class SearchServer {
  86. public:
  87. template <typename StringContainer>
  88. explicit SearchServer(const StringContainer& stop_words)
  89. : stop_words_(MakeUniqueNonEmptyStrings(stop_words)) // Extract non-empty stop words
  90. {
  91. if (!all_of(stop_words_.begin(), stop_words_.end(), IsValidWord)) {
  92. throw invalid_argument("Some of stop words are invalid"s);
  93. }
  94. }
  95.  
  96. explicit SearchServer(const string& stop_words_text)
  97. : SearchServer(SplitIntoWords(stop_words_text)) // Invoke delegating constructor from string container
  98. {
  99. }
  100.  
  101. void AddDocument(int document_id, const string& document, DocumentStatus status, const vector<int>& ratings) {
  102. if ((document_id < 0) || (documents_.count(document_id) > 0)) {
  103. throw invalid_argument("Invalid document_id"s);
  104. }
  105. const auto words = SplitIntoWordsNoStop(document);
  106.  
  107. const double inv_word_count = 1.0 / words.size();
  108. for (const string& word : words) {
  109. word_to_document_freqs_[word][document_id] += inv_word_count;
  110. }
  111. documents_.emplace(document_id, DocumentData{ ComputeAverageRating(ratings), status });
  112. document_ids_.push_back(document_id);
  113. }
  114.  
  115. template <typename DocumentPredicate>
  116. vector<Document> FindTopDocuments(const string& raw_query, DocumentPredicate document_predicate) const {
  117. const auto query = ParseQuery(raw_query);
  118.  
  119. auto matched_documents = FindAllDocuments(query, document_predicate);
  120.  
  121. sort(matched_documents.begin(), matched_documents.end(), [](const Document& lhs, const Document& rhs) {
  122. if (abs(lhs.relevance - rhs.relevance) < 1e-6) {
  123. return lhs.rating > rhs.rating;
  124. }
  125. else {
  126. return lhs.relevance > rhs.relevance;
  127. }
  128. });
  129. if (matched_documents.size() > MAX_RESULT_DOCUMENT_COUNT) {
  130. matched_documents.resize(MAX_RESULT_DOCUMENT_COUNT);
  131. }
  132.  
  133. return matched_documents;
  134. }
  135.  
  136. vector<Document> FindTopDocuments(const string& raw_query, DocumentStatus status) const {
  137. return FindTopDocuments(raw_query, [status](int document_id, DocumentStatus document_status, int rating) {
  138. return document_status == status;
  139. });
  140. }
  141.  
  142. vector<Document> FindTopDocuments(const string& raw_query) const {
  143. return FindTopDocuments(raw_query, DocumentStatus::ACTUAL);
  144. }
  145.  
  146. int GetDocumentCount() const {
  147. return static_cast<int>(documents_.size());
  148. }
  149.  
  150. int GetDocumentId(int index) const {
  151. return document_ids_.at(index);
  152. }
  153.  
  154. tuple<vector<string>, DocumentStatus> MatchDocument(const string& raw_query, int document_id) const {
  155. const auto query = ParseQuery(raw_query);
  156.  
  157. vector<string> matched_words;
  158. for (const string& word : query.plus_words) {
  159. if (word_to_document_freqs_.count(word) == 0) {
  160. continue;
  161. }
  162. if (word_to_document_freqs_.at(word).count(document_id)) {
  163. matched_words.push_back(word);
  164. }
  165. }
  166. for (const string& word : query.minus_words) {
  167. if (word_to_document_freqs_.count(word) == 0) {
  168. continue;
  169. }
  170. if (word_to_document_freqs_.at(word).count(document_id)) {
  171. matched_words.clear();
  172. break;
  173. }
  174. }
  175. return { matched_words, documents_.at(document_id).status };
  176. }
  177.  
  178. private:
  179. struct DocumentData {
  180. int rating;
  181. DocumentStatus status;
  182. };
  183. const set<string> stop_words_;
  184. map<string, map<int, double>> word_to_document_freqs_;
  185. map<int, DocumentData> documents_;
  186. vector<int> document_ids_;
  187.  
  188. bool IsStopWord(const string& word) const {
  189. return stop_words_.count(word) > 0;
  190. }
  191.  
  192. static bool IsValidWord(const string& word) {
  193. // A valid word must not contain special characters
  194. return none_of(word.begin(), word.end(), [](char c) {
  195. return c >= '\0' && c < ' ';
  196. });
  197. }
  198.  
  199. vector<string> SplitIntoWordsNoStop(const string& text) const {
  200. vector<string> words;
  201. for (const string& word : SplitIntoWords(text)) {
  202. if (!IsValidWord(word)) {
  203. throw invalid_argument("Word "s + word + " is invalid"s);
  204. }
  205. if (!IsStopWord(word)) {
  206. words.push_back(word);
  207. }
  208. }
  209. return words;
  210. }
  211.  
  212. static int ComputeAverageRating(const vector<int>& ratings) {
  213. if (ratings.empty()) {
  214. return 0;
  215. }
  216. int rating_sum = 0;
  217. for (const int rating : ratings) {
  218. rating_sum += rating;
  219. }
  220. return rating_sum / static_cast<int>(ratings.size());
  221. }
  222.  
  223. struct QueryWord {
  224. string data;
  225. bool is_minus;
  226. bool is_stop;
  227. };
  228.  
  229. QueryWord ParseQueryWord(const string& text) const {
  230. if (text.empty()) {
  231. throw invalid_argument("Query word is empty"s);
  232. }
  233. string word = text;
  234. bool is_minus = false;
  235. if (word[0] == '-') {
  236. is_minus = true;
  237. word = word.substr(1);
  238. }
  239. if (word.empty() || word[0] == '-' || !IsValidWord(word)) {
  240. throw invalid_argument("Query word "s + text + " is invalid");
  241. }
  242.  
  243. return { word, is_minus, IsStopWord(word) };
  244. }
  245.  
  246. struct Query {
  247. set<string> plus_words;
  248. set<string> minus_words;
  249. };
  250.  
  251. Query ParseQuery(const string& text) const {
  252. Query result;
  253. for (const string& word : SplitIntoWords(text)) {
  254. const auto query_word = ParseQueryWord(word);
  255. if (!query_word.is_stop) {
  256. if (query_word.is_minus) {
  257. result.minus_words.insert(query_word.data);
  258. }
  259. else {
  260. result.plus_words.insert(query_word.data);
  261. }
  262. }
  263. }
  264. return result;
  265. }
  266.  
  267. // Existence required
  268. double ComputeWordInverseDocumentFreq(const string& word) const {
  269. return log(GetDocumentCount() * 1.0 / word_to_document_freqs_.at(word).size());
  270. }
  271.  
  272. template <typename DocumentPredicate>
  273. vector<Document> FindAllDocuments(const Query& query, DocumentPredicate document_predicate) const {
  274. map<int, double> document_to_relevance;
  275. for (const string& word : query.plus_words) {
  276. if (word_to_document_freqs_.count(word) == 0) {
  277. continue;
  278. }
  279. const double inverse_document_freq = ComputeWordInverseDocumentFreq(word);
  280. for (const auto [document_id, term_freq] : word_to_document_freqs_.at(word)) {
  281. const auto& document_data = documents_.at(document_id);
  282. if (document_predicate(document_id, document_data.status, document_data.rating)) {
  283. document_to_relevance[document_id] += term_freq * inverse_document_freq;
  284. }
  285. }
  286. }
  287.  
  288. for (const string& word : query.minus_words) {
  289. if (word_to_document_freqs_.count(word) == 0) {
  290. continue;
  291. }
  292. for (const auto [document_id, _] : word_to_document_freqs_.at(word)) {
  293. document_to_relevance.erase(document_id);
  294. }
  295. }
  296.  
  297. vector<Document> matched_documents;
  298. for (const auto [document_id, relevance] : document_to_relevance) {
  299. matched_documents.push_back({ document_id, relevance, documents_.at(document_id).rating });
  300. }
  301. return matched_documents;
  302. }
  303. };
  304.  
  305.  
  306. template <typename It>
  307. class IteratorRange {
  308. public:
  309. IteratorRange(It start, It end) : start_(start), end_(end) {}
  310.  
  311. It begin() const {
  312. return start_;
  313. }
  314.  
  315. It end() const {
  316. return end_;
  317. }
  318.  
  319. int size() const {
  320. return static_cast<int>(distance(start_, end_));
  321. }
  322. private:
  323. It start_;
  324. It end_;
  325. };
  326.  
  327. template <typename It>
  328. class Paginator {
  329. public:
  330. Paginator(It start, It end, size_t page_size) {
  331. while (start <= end - 1) {
  332. if (start + page_size >= end) {
  333. It tmp_start = start;
  334. advance(start, distance(start, end));
  335. pages_.push_back(IteratorRange<It>(tmp_start, end));
  336. return;
  337. }
  338. pages_.push_back(IteratorRange<It>(start, start + page_size));
  339. advance(start, distance(start, start + page_size));
  340. }
  341. }
  342.  
  343. auto begin() const {
  344. return pages_.begin();
  345. }
  346.  
  347. auto end() const {
  348. return pages_.end();
  349. }
  350. private:
  351. vector<IteratorRange<It>> pages_;
  352. };
  353.  
  354. ostream& operator<<(ostream& os, const Document document) {
  355. os << "{ "s
  356. << "document_id = "s << document.id << ", "s
  357. << "relevance = "s << document.relevance << ", "s
  358. << "rating = "s << document.rating
  359. << " }"s;
  360. return os;
  361. }
  362.  
  363. template <typename It>
  364. ostream& operator<<(ostream& os, const IteratorRange<It> ir) {
  365. for (auto i = ir.begin(); i != ir.end(); ++i) {
  366. os << *i;
  367. }
  368. return os;
  369. }
  370.  
  371.  
  372. template <typename Container>
  373. auto Paginate(const Container& c, size_t page_size) {
  374. return Paginator(begin(c), end(c), page_size);
  375. }
  376.  
  377. class RequestQueue {
  378. public:
  379. explicit RequestQueue(const SearchServer& search_server)
  380. : srv(search_server) {
  381. ;
  382. }
  383. // сделаем "обёртки" для всех методов поиска, чтобы сохранять результаты для нашей статистики
  384. template <typename DocumentPredicate>
  385. vector<Document> AddFindRequest(const string& raw_query, DocumentPredicate document_predicate) {
  386. // напишите реализацию
  387. auto resultVector = srv.FindTopDocuments(raw_query, document_predicate);
  388.  
  389. AnswerToRequest_(resultVector, raw_query);
  390.  
  391. return resultVector;
  392. }
  393.  
  394. vector<Document> AddFindRequest(const string& raw_query, DocumentStatus status) {
  395. // напишите реализацию
  396. auto resultVector = srv.FindTopDocuments(raw_query, status);
  397. AnswerToRequest_(resultVector, raw_query);
  398.  
  399. return resultVector;
  400.  
  401. }
  402.  
  403. vector<Document> AddFindRequest(const string& raw_query) {
  404. // напишите реализацию
  405. auto resultVector = srv.FindTopDocuments(raw_query);
  406. AnswerToRequest_(resultVector, raw_query);
  407.  
  408. return resultVector;
  409. }
  410.  
  411. int GetNoResultRequests() const {
  412. //return count_requests_;
  413.  
  414. return count_if(requests_.begin(), requests_.end(), [](const QueryResult& a) {
  415. if (a.result_count_ == 0) {
  416. return true;
  417. }
  418. return false;
  419. ; });;
  420. }
  421. private:
  422. struct QueryResult {
  423. // определите, что должно быть в структуре
  424. string request = "";
  425. int result_count_ = 0;
  426. };
  427. deque<QueryResult> requests_;
  428. const static int min_in_day_ = 1440;
  429. //int count_requests_ = 0;
  430. const SearchServer& srv;
  431.  
  432. template<typename Type>
  433. void AnswerToRequest_(const Type& type, const string& str) {
  434. QueryResult query;
  435.  
  436. if (type.empty()) {
  437. query.result_count_ = 0;
  438. }
  439. else {
  440. ++query.result_count_;
  441. }
  442.  
  443. query.request = str;
  444. requests_.push_back(query);
  445.  
  446. if (requests_.size() > min_in_day_) {
  447. requests_.pop_front();
  448. }
  449.  
  450. }
  451. };
  452.  
  453.  
  454. int main() {
  455. SearchServer search_server("and in at"s);
  456. RequestQueue request_queue(search_server);
  457.  
  458. search_server.AddDocument(1, "curly cat curly tail"s, DocumentStatus::ACTUAL, { 7, 2, 7 });
  459. search_server.AddDocument(2, "curly dog and fancy collar"s, DocumentStatus::ACTUAL, { 1, 2, 3 });
  460. search_server.AddDocument(3, "big cat fancy collar "s, DocumentStatus::ACTUAL, { 1, 2, 8 });
  461. search_server.AddDocument(4, "big dog sparrow Eugene"s, DocumentStatus::ACTUAL, { 1, 3, 2 });
  462. search_server.AddDocument(5, "big dog sparrow Vasiliy"s, DocumentStatus::ACTUAL, { 1, 1, 1 });
  463.  
  464. // 1439 запросов с нулевым результатом
  465. for (int i = 0; i < 1439; ++i) {
  466. request_queue.AddFindRequest("empty request"s);
  467. }
  468. // все еще 1439 запросов с нулевым результатом
  469. request_queue.AddFindRequest("curly dog"s);
  470. // новые сутки, первый запрос удален, 1438 запросов с нулевым результатом
  471.  
  472. request_queue.AddFindRequest("big collar"s);
  473. // первый запрос удален, 1437 запросов с нулевым результатом
  474. request_queue.AddFindRequest("sparrow"s);
  475. cout << "Total empty requests: "s << request_queue.GetNoResultRequests() << endl;
  476. return 0;
  477. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement