index.js 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. module.exports = (function() {
  2. var __MODS__ = {};
  3. var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
  4. var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
  5. var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
  6. var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
  7. __DEFINE__(1682324647526, function(require, module, exports) {
  8. // Copyright Takatoshi Kondo 2021
  9. //
  10. // Distributed under the MIT License
  11. const NumberAllocator = require('./lib/number-allocator.js')
  12. module.exports.NumberAllocator = NumberAllocator
  13. }, function(modId) {var map = {"./lib/number-allocator.js":1682324647527}; return __REQUIRE__(map[modId], modId); })
  14. __DEFINE__(1682324647527, function(require, module, exports) {
  15. // Copyright Takatoshi Kondo 2021
  16. //
  17. // Distributed under the MIT License
  18. const SortedSet = require('js-sdsl').OrderedSet
  19. const debugTrace = require('debug')('number-allocator:trace')
  20. const debugError = require('debug')('number-allocator:error')
  21. /**
  22. * Interval constructor
  23. * @constructor
  24. * @param {Number} low - The lowest value of the interval
  25. * @param {Number} high - The highest value of the interval
  26. */
  27. function Interval (low, high) {
  28. this.low = low
  29. this.high = high
  30. }
  31. Interval.prototype.equals = function (other) {
  32. return this.low === other.low && this.high === other.high
  33. }
  34. Interval.prototype.compare = function (other) {
  35. if (this.low < other.low && this.high < other.low) return -1
  36. if (other.low < this.low && other.high < this.low) return 1
  37. return 0
  38. }
  39. /**
  40. * NumberAllocator constructor.
  41. * The all numbers are set to vacant status.
  42. * Time Complexity O(1)
  43. * @constructor
  44. * @param {Number} min - The maximum number of allocatable. The number must be integer.
  45. * @param {Number} maxh - The minimum number of allocatable. The number must be integer.
  46. */
  47. function NumberAllocator (min, max) {
  48. if (!(this instanceof NumberAllocator)) {
  49. return new NumberAllocator(min, max)
  50. }
  51. this.min = min
  52. this.max = max
  53. this.ss = new SortedSet(
  54. [],
  55. (lhs, rhs) => {
  56. return lhs.compare(rhs)
  57. }
  58. )
  59. debugTrace('Create')
  60. this.clear()
  61. }
  62. /**
  63. * Get the first vacant number. The status of the number is not updated.
  64. * Time Complexity O(1)
  65. * @return {Number} - The first vacant number. If all numbers are occupied, return null.
  66. * When alloc() is called then the same value will be allocated.
  67. */
  68. NumberAllocator.prototype.firstVacant = function () {
  69. if (this.ss.size() === 0) return null
  70. return this.ss.front().low
  71. }
  72. /**
  73. * Allocate the first vacant number. The number become occupied status.
  74. * Time Complexity O(1)
  75. * @return {Number} - The first vacant number. If all numbers are occupied, return null.
  76. */
  77. NumberAllocator.prototype.alloc = function () {
  78. if (this.ss.size() === 0) {
  79. debugTrace('alloc():empty')
  80. return null
  81. }
  82. const it = this.ss.begin()
  83. const low = it.pointer.low
  84. const high = it.pointer.high
  85. const num = low
  86. if (num + 1 <= high) {
  87. // x|----|
  88. this.ss.updateKeyByIterator(it, new Interval(low + 1, high))
  89. } else {
  90. this.ss.eraseElementByPos(0)
  91. }
  92. debugTrace('alloc():' + num)
  93. return num
  94. }
  95. /**
  96. * Use the number. The number become occupied status.
  97. * If the number has already been occupied, then return false.
  98. * Time Complexity O(logN) : N is the number of intervals (not numbers)
  99. * @param {Number} num - The number to request use.
  100. * @return {Boolean} - If `num` was not occupied, then return true, otherwise return false.
  101. */
  102. NumberAllocator.prototype.use = function (num) {
  103. const key = new Interval(num, num)
  104. const it = this.ss.lowerBound(key)
  105. if (!it.equals(this.ss.end())) {
  106. const low = it.pointer.low
  107. const high = it.pointer.high
  108. if (it.pointer.equals(key)) {
  109. // |x|
  110. this.ss.eraseElementByIterator(it)
  111. debugTrace('use():' + num)
  112. return true
  113. }
  114. // x |-----|
  115. if (low > num) return false
  116. // |x----|
  117. if (low === num) {
  118. // x|----|
  119. this.ss.updateKeyByIterator(it, new Interval(low + 1, high))
  120. debugTrace('use():' + num)
  121. return true
  122. }
  123. // |----x|
  124. if (high === num) {
  125. // |----|x
  126. this.ss.updateKeyByIterator(it, new Interval(low, high - 1))
  127. debugTrace('use():' + num)
  128. return true
  129. }
  130. // |--x--|
  131. // x|--|
  132. this.ss.updateKeyByIterator(it, new Interval(num + 1, high))
  133. // |--|x|--|
  134. this.ss.insert(new Interval(low, num - 1))
  135. debugTrace('use():' + num)
  136. return true
  137. }
  138. debugTrace('use():failed')
  139. return false
  140. }
  141. /**
  142. * Deallocate the number. The number become vacant status.
  143. * Time Complexity O(logN) : N is the number of intervals (not numbers)
  144. * @param {Number} num - The number to deallocate. The number must be occupied status.
  145. * In other words, the number must be allocated by alloc() or occupied be use().
  146. */
  147. NumberAllocator.prototype.free = function (num) {
  148. if (num < this.min || num > this.max) {
  149. debugError('free():' + num + ' is out of range')
  150. return
  151. }
  152. const key = new Interval(num, num)
  153. const it = this.ss.upperBound(key)
  154. if (it.equals(this.ss.end())) {
  155. // ....v
  156. if (it.equals(this.ss.begin())) {
  157. // Insert new interval
  158. this.ss.insert(key)
  159. return
  160. }
  161. it.pre()
  162. const low = it.pointer.high
  163. const high = it.pointer.high
  164. if (high + 1 === num) {
  165. // Concat to left
  166. this.ss.updateKeyByIterator(it, new Interval(low, num))
  167. } else {
  168. // Insert new interval
  169. this.ss.insert(key)
  170. }
  171. } else {
  172. if (it.equals(this.ss.begin())) {
  173. // v....
  174. if (num + 1 === it.pointer.low) {
  175. // Concat to right
  176. const low = it.pointer.high - 1
  177. const high = it.pointer.high
  178. this.ss.updateKeyByIterator(it, new Interval(low, high))
  179. } else {
  180. // Insert new interval
  181. this.ss.insert(key)
  182. }
  183. } else {
  184. // ..v..
  185. const rLow = it.pointer.low
  186. const rHigh = it.pointer.high
  187. it.pre()
  188. const lLow = it.pointer.low
  189. const lHigh = it.pointer.high
  190. if (lHigh + 1 === num) {
  191. if (num + 1 === rLow) {
  192. // Concat to left and right
  193. this.ss.eraseElementByIterator(it)
  194. const high = it.pointer.high
  195. this.ss.updateKeyByIterator(it, new Interval(lLow, high))
  196. } else {
  197. // Concat to left
  198. this.ss.updateKeyByIterator(it, new Interval(lLow, num))
  199. }
  200. } else {
  201. if (num + 1 === rLow) {
  202. // Concat to right
  203. this.ss.eraseElementByIterator(it.next())
  204. this.ss.insert(new Interval(num, rHigh))
  205. } else {
  206. // Insert new interval
  207. this.ss.insert(key)
  208. }
  209. }
  210. }
  211. }
  212. debugTrace('free():' + num)
  213. }
  214. /**
  215. * Clear all occupied numbers.
  216. * The all numbers are set to vacant status.
  217. * Time Complexity O(1)
  218. */
  219. NumberAllocator.prototype.clear = function () {
  220. debugTrace('clear()')
  221. this.ss.clear()
  222. this.ss.insert(new Interval(this.min, this.max))
  223. }
  224. /**
  225. * Get the number of intervals. Interval is internal structure of this library.
  226. * This function is for debugging.
  227. * Time Complexity O(1)
  228. * @return {Number} - The number of intervals.
  229. */
  230. NumberAllocator.prototype.intervalCount = function () {
  231. return this.ss.size()
  232. }
  233. /**
  234. * Dump the internal structor of the library.
  235. * This function is for debugging.
  236. * Time Complexity O(N) : N is the number of intervals (not numbers)
  237. */
  238. NumberAllocator.prototype.dump = function () {
  239. console.log('length:' + this.ss.size())
  240. for (const element of this.ss) {
  241. console.log(element)
  242. }
  243. }
  244. module.exports = NumberAllocator
  245. }, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
  246. return __REQUIRE__(1682324647526);
  247. })()
  248. //miniprogram-npm-outsideDeps=["js-sdsl","debug"]
  249. //# sourceMappingURL=index.js.map