Ladies_Man

Text Stats (Простой статистический анализ текста)

Dec 1st, 2014
360
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.78 KB | None | 0 0
  1. #include <iostream>
  2. #include <iterator>
  3. #include <string>
  4. #include <vector>
  5. #include <unordered_set>
  6. #include <set>
  7. #include <map>
  8. #include <string.h>
  9. #include <algorithm>
  10. #include "textstats.hpp"
  11.  
  12. using namespace std;
  13.  
  14. const unordered_set<char> delimiters {
  15.     '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
  16.     '+', '-', '=', '`', '{', '}', '[', ']', '|', '\\', ':', ';',
  17.     '\"', '\'', ',', '.', '/', '<', '>', '?', ' ', '\t', '\n'
  18. };
  19. // get_tokens разбивает текст, закодированный в ASCII, на слова,
  20. // с переводом всех букв к нижнему регистру.
  21. // Слово -- это последовательность символов, не являющихся разделителями.
  22. void get_tokens(
  23.     // [ВХОД] Текстовая строка.
  24.     const string &s,
  25.     // [ВХОД] Множество символов-разделителей.
  26.     const unordered_set<char> &delimiters,
  27.     // [ВЫХОД] Последовательность слов.
  28.     vector<string> &tokens
  29. )
  30. {
  31.     string buffer = s;
  32.     int buff_size = buffer.size();
  33.     string newstr;
  34.     newstr.clear();
  35.  
  36.     for (int i = 0; i < s.size(); i++) if (buffer[i] >= 'A' && buffer[i] <= 'Z') buffer[i] = tolower(buffer[i]);
  37.     if (delimiters.find(buffer[buff_size]) == delimiters.end()) buffer.append(".");
  38.     for (int i = 0, mark = 0; i < buff_size; i++, mark = 0) {
  39.         if (delimiters.find(buffer[i]) == delimiters.end()) newstr += buffer[i];
  40.         if (delimiters.find(buffer[i+1]) != delimiters.end()) mark = 1;
  41.         if (!newstr.empty() && mark == 1) {
  42.             tokens.push_back(newstr);
  43.             newstr.clear();
  44.         }
  45.     }
  46. }
  47.  
  48.  
  49. // get_type_freq составляет частотный словарь текста, в котором
  50. // для каждого слова указано количество его вхождений в текст.
  51. void get_type_freq(
  52.     // [ВХОД] Последовательность слов.
  53.     const vector<string> &tokens,
  54.     // [ВЫХОД] Частотный словарь
  55.     // (ключи -- слова, значения -- количества вхождений).
  56.     map<string, int> &freqdi
  57. )
  58. {
  59.     for (int i = 0; i < tokens.size(); i++) freqdi[tokens[i]]++;
  60. }
  61.  
  62.  
  63. // get_types составляет список уникальных слов, встречающихся в
  64. // тексте. Список должен быть отсортирован лексикографически.
  65. void get_types(
  66.     // [ВХОД] Последовательность слов.
  67.     const vector<string> &tokens,
  68.     // [ВЫХОД] Список уникальных слов.
  69.     vector<string> &wtypes
  70. )
  71. {
  72.     set<string> newset;
  73.     for (int i = 0; i < tokens.size(); i++) newset.insert(tokens[i]);
  74.  
  75.     //for (int i = 0; i < newset.size(); i++) {
  76.       for (auto& f : newset){
  77.         wtypes.push_back(f);
  78.     }
  79.     //sort (wtypes.begin(), wtypes.end());
  80. }
  81.  
  82.  
  83. // get_x_length_words формирует из списка уникальных слов новый
  84. // список, в который попадают только те слова, длина которых
  85. // не меньше x символов.
  86. void get_x_length_words(
  87.     // [ВХОД] Список уникальных слов.
  88.     const vector<string> &wtypes,
  89.     // [ВХОД] Минимальная длина слова.
  90.     int x,
  91.     // [ВЫХОД] Список слов, длина которых не меньше x.
  92.     vector<string> &words
  93. )
  94. {
  95.     for (int i = 0; i < wtypes.size(); i++) if (wtypes[i].size() >= x) words.push_back(wtypes[i]);
  96. }
  97.  
  98.  
  99. // get_x_freq_words формирует лексикографически отсортированный
  100. // список слов, взятых из частотного словаря, которые встречаются
  101. // в тексте не меньше x раз.
  102. void get_x_freq_words(
  103.     // [ВХОД] Частотный словарь
  104.     const map<string, int> &freqdi,
  105.     // [ВХОД] Минимальное количество вхождений.
  106.     int x,
  107.     // [ВЫХОД] Список слов, встречающихся не меньше x раз.
  108.     vector<string> &words
  109. )
  110. {
  111.     for (auto& f: freqdi) if (f.second >= x) words.push_back(f.first);
  112.     sort (words.begin(), words.end());
  113. }
  114.  
  115.  
  116. // get_words_by_length_dict составляет словарь, в котором каждый
  117. // ключ -- это длина слова, а значение -- это список слов заданной длины.
  118. void get_words_by_length_dict(
  119.     // [ВХОД] Список уникальных слов.
  120.     const vector<string> &wtypes,
  121.     // [ВЫХОД] Словарь распределения слов по длинам.
  122.     map<int, vector<string> > &lengthdi
  123. )
  124. {
  125.     int j, mark;
  126.     vector<int>sizes;
  127.     vector <string> strings;
  128.  
  129.     for (int i = 0; i < wtypes.size(); i++) {
  130.         for (j = 0, mark = 0; j < i; j++) {
  131.             if (wtypes[i].size() == wtypes[j].size()) {
  132.                 mark = 1;
  133.                 break;
  134.             }
  135.         }
  136.         if (0 == mark) sizes.push_back(wtypes[i].size());
  137.     }
  138.     for (int i = 0; i < sizes.size(); i++) {
  139.         for (j = 0, mark = 0; j < wtypes.size(); j++) {
  140.             if (wtypes[j].size() == sizes[i]) {
  141.                 strings.push_back(wtypes[j]);
  142.                 mark = 1;
  143.             }
  144.         }
  145.         if (mark == 1) {
  146.             lengthdi[sizes[i]] = strings;
  147.             strings.clear();
  148.         }
  149.     }
  150. }
  151.  
  152.  
  153. int main()
  154. {
  155.     // Ввод текста из стандартного потока ввода
  156.     // (при вводе текста из консоли в конце нужно нажать Ctrl-D).
  157.         //string text( (istreambuf_iterator<char>(cin)), (istreambuf_iterator<char>()) );
  158.    
  159. //string text = "In Key MaP the key values ARE generally used TO idenTify the elements thE mAp valuES store the content associated to key\n";
  160.  
  161.     // Итератор для вывода слов через пробел.
  162.     ostream_iterator<string> owords(cout, " ");
  163.  
  164.     // Разбиение текста на слова.
  165.     vector<string> tokens;
  166.     get_tokens(text, delimiters, tokens);
  167.     copy(tokens.begin(), tokens.end(), owords);
  168.     cout << endl;
  169.  
  170.     // Составление частотного словаря.
  171.     map<string, int> freqdi;
  172.     get_type_freq(tokens, freqdi);
  173.     for (auto p : freqdi) {
  174.         cout << "(" << p.first << " => " << p.second << ") ";
  175.     }
  176.     cout << endl;
  177.  
  178.     // Составление списка уникальных слов.
  179.     vector<string> wtypes;
  180.     get_types(tokens, wtypes);
  181.     copy(wtypes.begin(), wtypes.end(), owords);
  182.     cout << endl;
  183.  
  184.     // Вычисление средней длины уникальных слов.
  185.     int sum = 0;
  186.     for (auto w : wtypes) sum += w.length();
  187.     int med = tokens.size() > 0 ? (sum + wtypes.size() - 1)/wtypes.size() : 0;
  188.  
  189.     // Формирование списка слов, длина которых не ниже средней.
  190.     vector<string> long_wtypes;
  191.     get_x_length_words(wtypes, med, long_wtypes);
  192.     copy(long_wtypes.begin(), long_wtypes.end(), owords);
  193.     cout << endl;
  194.  
  195.     // Формирование списка слов, встречающихся больше одного раза.
  196.     vector<string> multi_wtypes;
  197.     get_x_freq_words(freqdi, 2, multi_wtypes);
  198.     copy(multi_wtypes.begin(), multi_wtypes.end(), owords);
  199.     cout << endl;
  200.  
  201.     // Составление словаря распределения слов по длинам.
  202.     map<int, vector<string> > lengthdi;
  203.     get_words_by_length_dict(wtypes, lengthdi);
  204.     for (auto p : lengthdi) {
  205.         cout << p.first << " => ";
  206.         copy(p.second.begin(), p.second.end(), owords);
  207.         cout << endl;
  208.     }
  209.  
  210.     return 0;
  211. }
Advertisement
Add Comment
Please, Sign In to add comment