File: hashed.cpp

package info (click to toggle)
boost1.74 1.74.0-9
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 464,084 kB
  • sloc: cpp: 3,338,324; xml: 131,293; python: 33,088; ansic: 14,336; asm: 4,034; sh: 3,351; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (124 lines) | stat: -rw-r--r-- 4,094 bytes parent folder | download | duplicates (15)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
/* Boost.MultiIndex example of use of hashed indices.
 *
 * Copyright 2003-2008 Joaquin M Lopez Munoz.
 * Distributed under the Boost Software License, Version 1.0.
 * (See accompanying file LICENSE_1_0.txt or copy at
 * http://www.boost.org/LICENSE_1_0.txt)
 *
 * See http://www.boost.org/libs/multi_index for library home page.
 */

#if !defined(NDEBUG)
#define BOOST_MULTI_INDEX_ENABLE_INVARIANT_CHECKING
#define BOOST_MULTI_INDEX_ENABLE_SAFE_MODE
#endif

#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/tokenizer.hpp>
#include <iomanip>
#include <iostream>
#include <string>

using boost::multi_index_container;
using namespace boost::multi_index;

/* word_counter keeps the ocurrences of words inserted. A hashed
 * index allows for fast checking of preexisting entries.
 */

struct word_counter_entry
{
  std::string  word;
  unsigned int occurrences;

  word_counter_entry(std::string word_):word(word_),occurrences(0){}
};

/* see Compiler specifics: Use of member_offset for info on
 * BOOST_MULTI_INDEX_MEMBER
 */

typedef multi_index_container<
  word_counter_entry,
  indexed_by<
    ordered_non_unique<
      BOOST_MULTI_INDEX_MEMBER(word_counter_entry,unsigned int,occurrences),
      std::greater<unsigned int> /* sorted beginning with most frequent */
    >,
    hashed_unique<
      BOOST_MULTI_INDEX_MEMBER(word_counter_entry,std::string,word)
    >
  >
> word_counter;

/* utilities */

template<typename T>
struct increment
{
  void operator()(T& x)const{++x;}
};

typedef boost::tokenizer<boost::char_separator<char> > text_tokenizer;

int main()
{
  /* boostinspect:noascii */

  std::string text=
    "En un lugar de la Mancha, de cuyo nombre no quiero acordarme, no ha "
    "mucho tiempo que viva un hidalgo de los de lanza en astillero, adarga "
    "antigua, rocn flaco y galgo corredor. Una olla de algo ms vaca que "
    "carnero, salpicn las ms noches, duelos y quebrantos los sbados, "
    "lantejas los viernes, algn palomino de aadidura los domingos, "
    "consuman las tres partes de su hacienda. El resto della concluan sayo "
    "de velarte, calzas de velludo para las fiestas, con sus pantuflos de lo "
    "mesmo, y los das de entresemana se honraba con su vellor de lo ms "
    "fino. Tena en su casa una ama que pasaba de los cuarenta, y una "
    "sobrina que no llegaba a los veinte, y un mozo de campo y plaza, que "
    "as ensillaba el rocn como tomaba la podadera. Frisaba la edad de "
    "nuestro hidalgo con los cincuenta aos; era de complexin recia, seco "
    "de carnes, enjuto de rostro, gran madrugador y amigo de la caza. "
    "Quieren decir que tena el sobrenombre de Quijada, o Quesada, que en "
    "esto hay alguna diferencia en los autores que deste caso escriben; "
    "aunque, por conjeturas verosmiles, se deja entender que se llamaba "
    "Quejana. Pero esto importa poco a nuestro cuento; basta que en la "
    "narracin dl no se salga un punto de la verdad.";

  /* feed the text into the container */

  word_counter   wc;
  text_tokenizer tok(text,boost::char_separator<char>(" \t\n.,;:!?'\"-"));
  unsigned int   total_occurrences=0;
  for(text_tokenizer::iterator it=tok.begin(),it_end=tok.end();
      it!=it_end;++it){
    /* Insert the word into the container. If duplicate, wit will point to
     * the preexistent entry.
     */

    ++total_occurrences;
    word_counter::iterator wit=wc.insert(*it).first;

    /* Increment occurrences.
     * In a lambda-capable compiler, this can be written as:
     *   wc.modify_key(wit,++_1);
     */

    wc.modify_key(wit,increment<unsigned int>());
  }

  /* list words by frequency of appearance */

  std::cout<<std::fixed<<std::setprecision(2);
  for(word_counter::iterator wit=wc.begin(),wit_end=wc.end();
      wit!=wit_end;++wit){
    std::cout<<std::setw(11)<<wit->word<<": "
             <<std::setw(5) <<100.0*wit->occurrences/total_occurrences<<"%"
             <<std::endl;
  }

  return 0;
}