counters.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #ifndef __COUNTERS_H
  2. #define __COUNTERS_H
  3. #include <string>
  4. #include <map>
  5. #include "random.h"
  6. namespace counters {
  7. struct Counts {
  8. std::map< unsigned int, std::map<tag_t, unsigned int> > data;
  9. void init(tag_t tag, unsigned int level, unsigned int maxc) {
  10. if (maxc > 0) {
  11. data[level][tag] = maxc;
  12. }
  13. }
  14. tag_t find(rnd::Generator& rng, unsigned int level) {
  15. auto d = data.find(level);
  16. if (d == data.end() || d->second.empty())
  17. return tag_t();
  18. size_t n = rng.n(d->second.size());
  19. auto i = d->second.begin();
  20. while (n > 0) {
  21. ++i;
  22. --n;
  23. }
  24. return i->first;
  25. }
  26. std::map<tag_t, unsigned int> take(rnd::Generator& rng, unsigned int level,
  27. unsigned int n = 1, bool exclusive = false) {
  28. std::map<tag_t, unsigned int> ret;
  29. while (level >= 0 && n > 0) {
  30. if (data.count(level) == 0) {
  31. if (level == 0 || exclusive) {
  32. return ret;
  33. } else {
  34. --level;
  35. continue;
  36. }
  37. }
  38. std::vector<double> weights;
  39. for (const auto& i : data[level]) {
  40. weights.push_back(i.second);
  41. }
  42. std::discrete_distribution<unsigned int> d(weights.begin(), weights.end());
  43. unsigned int ntag = d(rng.gen);
  44. auto i = data[level].begin();
  45. while (ntag > 0) {
  46. ++i;
  47. --ntag;
  48. }
  49. tag_t tag = i->first;
  50. unsigned int takecount = take(level, tag, n);
  51. n -= takecount;
  52. ret[tag] += takecount;
  53. }
  54. return ret;
  55. }
  56. unsigned int take(unsigned int level, tag_t tag, unsigned int n = 1) {
  57. auto levi = data.find(level);
  58. if (levi == data.end()) {
  59. return 0;
  60. }
  61. auto tagi = levi->second.find(tag);
  62. if (tagi == levi->second.end()) {
  63. return 0;
  64. }
  65. unsigned int& totn = tagi->second;
  66. if (n < totn) {
  67. totn -= n;
  68. return n;
  69. } else {
  70. unsigned int ret = totn;
  71. levi->second.erase(tagi);
  72. if (levi->second.size() == 0) {
  73. data.erase(levi);
  74. }
  75. return ret;
  76. }
  77. }
  78. unsigned int take(tag_t tag, unsigned int n = 1) {
  79. unsigned int ret = 0;
  80. if (data.size() == 0) {
  81. return ret;
  82. }
  83. unsigned int maxlevel = data.rbegin()->first;
  84. for (unsigned int lev = 0; lev <= maxlevel; ++lev) {
  85. unsigned int takecount = take(lev, tag, n);
  86. n -= takecount;
  87. ret += takecount;
  88. if (n == 0) {
  89. break;
  90. }
  91. }
  92. return ret;
  93. }
  94. void replace(unsigned int level, tag_t tag, unsigned int n = 1) {
  95. if (n > 0) {
  96. data[level][tag] += n;
  97. }
  98. }
  99. bool has(unsigned int level, tag_t tag) {
  100. auto i = data.find(level);
  101. if (i == data.end()) return false;
  102. auto j = i->second.find(tag);
  103. if (j == i->second.end()) return false;
  104. if (j->second < 1) return false;
  105. return true;
  106. }
  107. template <typename FUNC>
  108. void change_counts(FUNC f) {
  109. for (auto i = data.begin(); i != data.end(); ) {
  110. for (auto j = i->second.begin(); j != i->second.end(); ) {
  111. unsigned int newcount = f(j->first, j->second);
  112. if (newcount == 0) {
  113. j = i->second.erase(j);
  114. } else {
  115. j->second = newcount;
  116. ++j;
  117. }
  118. }
  119. if (i->second.empty()) {
  120. i = data.erase(i);
  121. } else {
  122. ++i;
  123. }
  124. }
  125. }
  126. };
  127. }
  128. #endif