ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Combinatorics.h
Go to the documentation of this file.
1 #ifndef ROSE_Combinatorics_H
2 #define ROSE_Combinatorics_H
3 
5 
6 #include <algorithm>
7 #include <cassert>
8 #include <list>
9 #include <stdint.h>
10 #include <string>
11 #include <vector>
12 
13 namespace Combinatorics {
14 
16 template<typename T>
17 static T
19 {
20  T retval = 1;
21  while (n>1) {
22  T next = retval * n--;
23  assert(next>retval); // overflow
24  retval = next;
25  }
26  return retval;
27 }
28 
31 bool flip_coin();
32 
38 template<typename T>
39 static void
40 permute(std::vector<T> &values/*in,out*/, uint64_t pn, size_t sz=(size_t)(-1))
41 {
42  if ((size_t)(-1)==sz)
43  sz = values.size();
44  assert(sz<=values.size());
45  assert(pn<factorial(sz));
46  for (size_t i=0; i<sz; ++i) {
47  uint64_t radix = sz - i;
48  uint64_t idx = pn % radix;
49  std::swap(values[i+idx], values[i]);
50  pn /= radix;
51  }
52 }
53 
58 template<typename T>
59 void
60 shuffle(std::vector<T> &vector, size_t nitems=(size_t)(-1), size_t limit=(size_t)(-1), LinearCongruentialGenerator *lcg=NULL)
61 {
62  static LinearCongruentialGenerator my_lcg;
63  if (!lcg)
64  lcg = &my_lcg;
65  nitems = std::min(nitems, vector.size());
66  limit = std::min(limit, nitems);
67 
68  for (size_t i=0; i<limit; ++i)
69  std::swap(vector[i], vector[lcg->next()%nitems]);
70 }
71 
76 std::vector<uint8_t> sha1_digest(const uint8_t *data, size_t size);
77 std::vector<uint8_t> sha1_digest(const std::vector<uint8_t> &data);
78 std::vector<uint8_t> sha1_digest(const std::string &data);
84 uint64_t fnv1a64_digest(const uint8_t *data, size_t size);
85 uint64_t fnv1a64_digest(const std::vector<uint8_t> &data);
86 uint64_t fnv1a64_digest(const std::string &data);
94 std::string digest_to_string(const uint8_t *data, size_t size);
95 std::string digest_to_string(const std::vector<uint8_t> &digest);
96 std::string digest_to_string(const std::string &data);
99 // Stack for Damerau-Levenshtein distance
100 template<typename T>
101 struct DL_Stack {
102  typedef std::pair<T/*key*/, size_t/*value*/> KeyVal;
103  typedef std::list<KeyVal> KeyValList;
105 
106  void unique_push_zero(const T& key) {
107  for (typename KeyValList::iterator pi=pairs.begin(); pi!=pairs.end(); ++pi) {
108  if (pi->first==key)
109  return;
110  }
111  pairs.push_front(KeyVal(key, 0));
112  }
113 
114  size_t& operator[](const T& key) {
115  for (typename KeyValList::iterator pi=pairs.begin(); pi!=pairs.end(); ++pi) {
116  if (pi->first==key)
117  return pi->second;
118  }
119  assert(!"not found");
120  abort();
121  }
122 };
123 
126 template<typename T>
127 size_t
128 damerau_levenshtein_distance(const std::vector<T> &src, const std::vector<T> &tgt)
129 {
130  // Based on the C# implementation on the wikipedia page
131  if (src.empty() || tgt.empty())
132  return std::max(src.size(), tgt.size());
133 
134  const size_t x = src.size();
135  const size_t y = tgt.size();
136  std::vector<std::vector<size_t> > score(x+2, std::vector<size_t>(y+2, 0));
137  size_t score_ceil = x + y;
138  score[0][0] = score_ceil;
139  for (size_t i=0; i<=x; ++i) {
140  score[i+1][1] = i;
141  score[i+1][0] = score_ceil;
142  }
143  for (size_t j=0; j<=y; ++j) {
144  score[1][j+1] = j;
145  score[0][j+1] = score_ceil;
146  }
147 
148  DL_Stack<T> dict;
149  for (size_t i=0; i<x; ++i)
150  dict.unique_push_zero(src[i]);
151  for (size_t j=0; j<y; ++j)
152  dict.unique_push_zero(tgt[j]);
153 
154  for (size_t i=1; i<=x; ++i) {
155  size_t db = 0;
156  for (size_t j=1; j<=y; ++j) {
157  size_t i1 = dict[tgt[j-1]];
158  size_t j1 = db;
159  if (src[i-1]==tgt[j-1]) {
160  score[i+1][j+1] = score[i][j];
161  db = j;
162  } else {
163  score[i+1][j+1] = std::min(score[i][j], std::min(score[i+1][j], score[i][j+1])) + 1;
164  }
165  // swaps
166  score[i+1][j+1] = std::min(score[i+1][j+1], score[i1][j1] + (i-i1-1) + 1 + (j-j1-1));
167  }
168  dict[src[i-1]] = i;
169  }
170 
171  return score[x+1][y+1];
172 }
173 
175 template<typename T>
176 size_t
177 levenshtein_distance(const std::vector<T> &src, const std::vector<T> &tgt)
178 {
179  // Implementation is cut-n-pasted from above, but removed the line for swaps and associated variables
180  if (src.empty() || tgt.empty())
181  return std::max(src.size(), tgt.size());
182 
183  const size_t x = src.size();
184  const size_t y = tgt.size();
185  std::vector<std::vector<size_t> > score(x+2, std::vector<size_t>(y+2, 0));
186  size_t score_ceil = x + y;
187  score[0][0] = score_ceil;
188  for (size_t i=0; i<=x; ++i) {
189  score[i+1][1] = i;
190  score[i+1][0] = score_ceil;
191  }
192  for (size_t j=0; j<=y; ++j) {
193  score[1][j+1] = j;
194  score[0][j+1] = score_ceil;
195  }
196 
197  DL_Stack<T> dict;
198  for (size_t i=0; i<x; ++i)
199  dict.unique_push_zero(src[i]);
200  for (size_t j=0; j<y; ++j)
201  dict.unique_push_zero(tgt[j]);
202 
203  for (size_t i=1; i<=x; ++i) {
204  size_t db = 0;
205  for (size_t j=1; j<=y; ++j) {
206  if (src[i-1]==tgt[j-1]) {
207  score[i+1][j+1] = score[i][j];
208  db = j;
209  } else {
210  score[i+1][j+1] = std::min(score[i][j], std::min(score[i+1][j], score[i][j+1])) + 1;
211  }
212  }
213  dict[src[i-1]] = i;
214  }
215 
216  return score[x+1][y+1];
217 }
218 
219 
220 } // namespace
221 #endif