diff --git a/dist/SortedSet.js b/dist/SortedSet.js index b982158..66f4507 100644 --- a/dist/SortedSet.js +++ b/dist/SortedSet.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript 2.5.1 (function() { - var AbstractSortedSet, ArrayStrategy, BinaryTreeStrategy, RedBlackTreeStrategy, SortedSet, enums; + var AbstractSortedSet, ArrayStrategy, BinaryTreeStrategy, RedBlackTreeStrategy, SortedSet, insertConflictResolvers; AbstractSortedSet = require('./SortedSet/AbstractSortedSet'); @@ -10,7 +10,7 @@ RedBlackTreeStrategy = require('./SortedSet/RedBlackTreeStrategy'); - enums = require('./enums'); + insertConflictResolvers = require('./insertConflictResolvers'); SortedSet = class SortedSet extends AbstractSortedSet { constructor(options) { @@ -19,7 +19,7 @@ options.comparator || (options.comparator = function(a, b) { return (a || 0) - (b || 0); }); - options.insertBehavior || (options.insertBehavior = enums.insertBehaviors.throw); + options.onInsertConflict || (options.onInsertConflict = insertConflictResolvers.throw); super(options); } @@ -31,8 +31,14 @@ SortedSet.RedBlackTreeStrategy = RedBlackTreeStrategy; - SortedSet.insertBehaviors = enums.insertBehaviors; + SortedSet.onInsertConflictThrow = insertConflictResolvers.throw; + + SortedSet.onInsertConflictReplace = insertConflictResolvers.replace; + + SortedSet.onInsertConflictIgnore = insertConflictResolvers.ignore; module.exports = SortedSet; }).call(this); + +//# sourceMappingURL=SortedSet.js.map diff --git a/dist/SortedSet.js.map b/dist/SortedSet.js.map new file mode 100644 index 0000000..f8ecc09 --- /dev/null +++ b/dist/SortedSet.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "SortedSet.js", + "sourceRoot": "..", + "sources": [ + "src/SortedSet.coffee" + ], + "names": [], + "mappings": ";AAAA;AAAA,MAAA,iBAAA,EAAA,aAAA,EAAA,kBAAA,EAAA,oBAAA,EAAA,SAAA,EAAA;;EAAA,iBAAA,GAAoB,OAAA,CAAQ,+BAAR;;EACpB,aAAA,GAAgB,OAAA,CAAQ,2BAAR;;EAChB,kBAAA,GAAqB,OAAA,CAAQ,gCAAR;;EACrB,oBAAA,GAAuB,OAAA,CAAQ,kCAAR;;EACvB,uBAAA,GAA0B,OAAA,CAAQ,2BAAR;;EAEpB,YAAN,MAAA,UAAA,QAAwB,kBAAxB;IACE,WAAa,CAAC,OAAD,CAAA;MACX,YAAA,UAAY,CAAA;MACZ,OAAO,CAAC,aAAR,OAAO,CAAC,WAAa;MACrB,OAAO,CAAC,eAAR,OAAO,CAAC,aAAe,QAAA,CAAC,CAAD,EAAI,CAAJ,CAAA;eAAU,CAAC,CAAA,IAAK,CAAN,CAAA,GAAW,CAAC,CAAA,IAAK,CAAN;MAArB;MACvB,OAAO,CAAC,qBAAR,OAAO,CAAC,mBAAqB,uBAAuB,CAAC;WACrD,CAAM,OAAN;IALW;;EADf;;EAQA,SAAS,CAAC,aAAV,GAA0B;;EAC1B,SAAS,CAAC,kBAAV,GAA+B;;EAC/B,SAAS,CAAC,oBAAV,GAAiC;;EAEjC,SAAS,CAAC,qBAAV,GAAkC,uBAAuB,CAAC;;EAC1D,SAAS,CAAC,uBAAV,GAAoC,uBAAuB,CAAC;;EAC5D,SAAS,CAAC,sBAAV,GAAmC,uBAAuB,CAAC;;EAE3D,MAAM,CAAC,OAAP,GAAiB;AAtBjB", + "sourcesContent": [ + "AbstractSortedSet = require('./SortedSet/AbstractSortedSet')\nArrayStrategy = require('./SortedSet/ArrayStrategy')\nBinaryTreeStrategy = require('./SortedSet/BinaryTreeStrategy')\nRedBlackTreeStrategy = require('./SortedSet/RedBlackTreeStrategy')\ninsertConflictResolvers = require('./insertConflictResolvers')\n\nclass SortedSet extends AbstractSortedSet\n constructor: (options) ->\n options ||= {}\n options.strategy ||= RedBlackTreeStrategy\n options.comparator ||= (a, b) -> (a || 0) - (b || 0)\n options.onInsertConflict ||= insertConflictResolvers.throw\n super(options)\n\nSortedSet.ArrayStrategy = ArrayStrategy\nSortedSet.BinaryTreeStrategy = BinaryTreeStrategy\nSortedSet.RedBlackTreeStrategy = RedBlackTreeStrategy\n\nSortedSet.onInsertConflictThrow = insertConflictResolvers.throw\nSortedSet.onInsertConflictReplace = insertConflictResolvers.replace\nSortedSet.onInsertConflictIgnore = insertConflictResolvers.ignore\n\nmodule.exports = SortedSet\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/AbstractBinaryTreeStrategy.js b/dist/SortedSet/AbstractBinaryTreeStrategy.js index 912ec4a..0d14eb2 100644 --- a/dist/SortedSet/AbstractBinaryTreeStrategy.js +++ b/dist/SortedSet/AbstractBinaryTreeStrategy.js @@ -73,3 +73,5 @@ module.exports = AbstractBinaryTree; }).call(this); + +//# sourceMappingURL=AbstractBinaryTreeStrategy.js.map diff --git a/dist/SortedSet/AbstractBinaryTreeStrategy.js.map b/dist/SortedSet/AbstractBinaryTreeStrategy.js.map new file mode 100644 index 0000000..4e0f15b --- /dev/null +++ b/dist/SortedSet/AbstractBinaryTreeStrategy.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "AbstractBinaryTreeStrategy.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/AbstractBinaryTreeStrategy.coffee" + ], + "names": [], + "mappings": ";AAAA;AAAA,MAAA,kBAAA,EAAA,kBAAA,EAAA;;EAAA,kBAAA,GAAqB,OAAA,CAAQ,sBAAR;;EAErB,kBAAA,GAAqB,QAAA,CAAC,IAAD,EAAO,QAAP,CAAA;IACnB,IAAG,IAAA,KAAU,IAAb;MACE,kBAAA,CAAmB,IAAI,CAAC,IAAxB,EAA8B,QAA9B;MACA,QAAA,CAAS,IAAI,CAAC,KAAd;MACA,kBAAA,CAAmB,IAAI,CAAC,KAAxB,EAA+B,QAA/B,EAHF;;WAIA;EALmB,EAFrB;;;;EAWM,qBAAN,MAAA,mBAAA;IACE,OAAS,CAAA,CAAA;AACX,UAAA;MAAI,GAAA,GAAM;MACN,kBAAA,CAAmB,IAAC,CAAA,IAApB,EAA0B,QAAA,CAAC,KAAD,CAAA;eAAW,GAAG,CAAC,IAAJ,CAAS,KAAT;MAAX,CAA1B;aACA;IAHO;;IAKT,KAAO,CAAA,CAAA;aACL,IAAC,CAAA,IAAD,GAAQ;IADH;;IAGP,WAAa,CAAC,QAAD,EAAW,SAAX,EAAsB,OAAtB,CAAA;AACf,UAAA;MAAI,CAAA,GAAI;MACJ,kBAAA,CAAmB,IAAC,CAAA,IAApB,EAA0B,QAAA,CAAC,KAAD,CAAA;QACxB,QAAQ,CAAC,IAAT,CAAc,OAAd,EAAuB,KAAvB,EAA8B,CAA9B,EAAiC,SAAjC;eACA,CAAA,IAAK;MAFmB,CAA1B;aAGA;IALW;;IAOb,QAAU,CAAC,KAAD,CAAA;AACZ,UAAA,GAAA,EAAA,UAAA,EAAA;MAAI,UAAA,GAAa,IAAC,CAAA;MAEd,IAAA,GAAO,IAAC,CAAA;AACR,aAAM,IAAA,KAAU,IAAhB;QACE,GAAA,GAAM,UAAA,CAAW,KAAX,EAAkB,IAAI,CAAC,KAAvB;QACN,IAAG,GAAA,KAAO,CAAV;AACE,gBADF;SAAA,MAEK,IAAG,GAAA,GAAM,CAAT;UACH,IAAA,GAAO,IAAI,CAAC,KADT;SAAA,MAAA;UAGH,IAAA,GAAO,IAAI,CAAC,MAHT;;MAJP;aASA,IAAA,KAAU,IAAV,IAAkB,IAAI,CAAC,KAAL,KAAc;IAbxB;;IAeV,YAAc,CAAC,KAAD,CAAA;aAAW,kBAAkB,CAAC,IAAnB,CAAwB,IAAxB,EAA8B,KAA9B,EAAqC,IAAC,CAAA,UAAtC;IAAX;;IACd,aAAe,CAAA,CAAA;aAAG,kBAAkB,CAAC,IAAnB,CAAwB,IAAxB;IAAH;;IACf,WAAa,CAAA,CAAA;aAAG,kBAAkB,CAAC,KAAnB,CAAyB,IAAzB;IAAH;;EAjCf;;EAmCA,MAAM,CAAC,OAAP,GAAiB;AA9CjB", + "sourcesContent": [ + "BinaryTreeIterator = require('./BinaryTreeIterator')\n\nbinaryTreeTraverse = (node, callback) ->\n if node isnt null\n binaryTreeTraverse(node.left, callback)\n callback(node.value)\n binaryTreeTraverse(node.right, callback)\n undefined\n\n# An AbstractBinaryTree has a @root. @root is null or an object with\n# `.left`, `.right` and `.value` properties.\nclass AbstractBinaryTree\n toArray: ->\n ret = []\n binaryTreeTraverse(@root, (value) -> ret.push(value))\n ret\n\n clear: ->\n @root = null\n\n forEachImpl: (callback, sortedSet, thisArg) ->\n i = 0\n binaryTreeTraverse @root, (value) ->\n callback.call(thisArg, value, i, sortedSet)\n i += 1\n undefined\n\n contains: (value) ->\n comparator = @comparator\n\n node = @root\n while node isnt null\n cmp = comparator(value, node.value)\n if cmp == 0\n break\n else if cmp < 0\n node = node.left\n else\n node = node.right\n\n node isnt null && node.value == value\n\n findIterator: (value) -> BinaryTreeIterator.find(this, value, @comparator)\n beginIterator: -> BinaryTreeIterator.left(this)\n endIterator: -> BinaryTreeIterator.right(this)\n\nmodule.exports = AbstractBinaryTree\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/AbstractSortedSet.js b/dist/SortedSet/AbstractSortedSet.js index a9a0f9d..9f841d3 100644 --- a/dist/SortedSet/AbstractSortedSet.js +++ b/dist/SortedSet/AbstractSortedSet.js @@ -10,8 +10,8 @@ if ((options != null ? options.comparator : void 0) == null) { throw 'Must pass options.comparator, a comparator'; } - if ((options != null ? options.insertBehavior : void 0) == null) { - throw 'Must pass options.insertBehavior, a number'; + if ((options != null ? options.onInsertConflict : void 0) == null) { + throw 'Must pass options.onInsertConflict, a function'; } this.priv = new options.strategy(options); this.length = 0; @@ -131,3 +131,5 @@ }; }).call(this); + +//# sourceMappingURL=AbstractSortedSet.js.map diff --git a/dist/SortedSet/AbstractSortedSet.js.map b/dist/SortedSet/AbstractSortedSet.js.map new file mode 100644 index 0000000..9a03b7e --- /dev/null +++ b/dist/SortedSet/AbstractSortedSet.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "AbstractSortedSet.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/AbstractSortedSet.coffee" + ], + "names": [], + "mappings": ";AAAA;AAAA,MAAA;;EAAA,MAAM,CAAC,OAAP,GAAuB,oBAAN,MAAA,kBAAA;IACf,WAAa,CAAC,OAAD,CAAA;MACX,IAAmD,qDAAnD;QAAA,MAAM,yCAAN;;MACA,IAAuD,uDAAvD;QAAA,MAAM,6CAAN;;MACA,IAA2D,6DAA3D;QAAA,MAAM,iDAAN;;MACA,IAAC,CAAA,IAAD,GAAQ,IAAI,OAAO,CAAC,QAAZ,CAAqB,OAArB;MACR,IAAC,CAAA,MAAD,GAAU;IALC;;IAOb,MAAQ,CAAC,KAAD,CAAA;MACN,IAAC,CAAA,IAAI,CAAC,MAAN,CAAa,KAAb;MACA,IAAC,CAAA,MAAD,IAAW;aACX;IAHM;;IAKR,MAAQ,CAAC,KAAD,CAAA;MACN,IAAC,CAAA,IAAI,CAAC,MAAN,CAAa,KAAb;MACA,IAAC,CAAA,MAAD,IAAW;aACX;IAHM;;IAKR,KAAO,CAAA,CAAA;MACL,IAAC,CAAA,IAAI,CAAC,KAAN,CAAA;MACA,IAAC,CAAA,MAAD,GAAU;aACV;IAHK;;IAKP,QAAU,CAAC,KAAD,CAAA;aACR,IAAC,CAAA,IAAI,CAAC,QAAN,CAAe,KAAf;IADQ,CAtBZ;;;IA0BE,OAAS,CAAA,CAAA;aAAG,IAAC,CAAA,IAAI,CAAC,OAAN,CAAA;IAAH;;IAET,OAAS,CAAC,QAAD,EAAW,OAAX,CAAA;MACP,IAAC,CAAA,IAAI,CAAC,WAAN,CAAkB,QAAlB,EAA4B,IAA5B,EAAkC,OAAlC;aACA;IAFO;;IAIT,GAAK,CAAC,QAAD,EAAW,OAAX,CAAA;AACP,UAAA;MAAI,GAAA,GAAM;MACN,IAAC,CAAA,OAAD,CAAS,QAAA,CAAC,KAAD,EAAQ,KAAR,EAAe,IAAf,CAAA;eACP,GAAG,CAAC,IAAJ,CAAS,QAAQ,CAAC,IAAT,CAAc,OAAd,EAAuB,KAAvB,EAA8B,KAA9B,EAAqC,IAArC,CAAT;MADO,CAAT;aAEA;IAJG;;IAML,MAAQ,CAAC,QAAD,EAAW,OAAX,CAAA;AACV,UAAA;MAAI,GAAA,GAAM;MACN,IAAC,CAAA,OAAD,CAAS,QAAA,CAAC,KAAD,EAAQ,KAAR,EAAe,IAAf,CAAA;QACP,IAAmB,QAAQ,CAAC,IAAT,CAAc,OAAd,EAAuB,KAAvB,EAA8B,KAA9B,EAAqC,IAArC,CAAnB;iBAAA,GAAG,CAAC,IAAJ,CAAS,KAAT,EAAA;;MADO,CAAT;aAEA;IAJM;;IAMR,KAAO,CAAC,QAAD,EAAW,OAAX,CAAA;AACT,UAAA;MAAI,GAAA,GAAM;MACN,IAAC,CAAA,OAAD,CAAS,QAAA,CAAC,KAAD,EAAQ,KAAR,EAAe,IAAf,CAAA;QACP,IAAe,GAAA,IAAO,CAAC,QAAQ,CAAC,IAAT,CAAc,OAAd,EAAuB,KAAvB,EAA8B,KAA9B,EAAqC,IAArC,CAAvB;iBAAA,GAAA,GAAM,MAAN;;MADO,CAAT;aAEA;IAJK;;IAMP,IAAM,CAAC,QAAD,EAAW,OAAX,CAAA;AACR,UAAA;MAAI,GAAA,GAAM;MACN,IAAC,CAAA,OAAD,CAAS,QAAA,CAAC,KAAD,EAAQ,KAAR,EAAe,IAAf,CAAA;QACP,IAAc,CAAC,GAAD,IAAQ,QAAQ,CAAC,IAAT,CAAc,OAAd,EAAuB,KAAvB,EAA8B,KAA9B,EAAqC,IAArC,CAAtB;iBAAA,GAAA,GAAM,KAAN;;MADO,CAAT;aAEA;IAJI,CAlDR;;;;;;;;;;;;;;;;;;;;;;;;;IA+EE,YAAc,CAAC,KAAD,CAAA;aACZ,IAAC,CAAA,IAAI,CAAC,YAAN,CAAmB,KAAnB;IADY,CA/EhB;;;IAmFE,aAAe,CAAA,CAAA;aACb,IAAC,CAAA,IAAI,CAAC,aAAN,CAAA;IADa,CAnFjB;;;IAuFE,WAAa,CAAA,CAAA;aACX,IAAC,CAAA,IAAI,CAAC,WAAN,CAAA;IADW;;EAxFE;AAAjB", + "sourcesContent": [ + "module.exports = class AbstractSortedSet\n constructor: (options) ->\n throw 'Must pass options.strategy, a strategy' if !options?.strategy?\n throw 'Must pass options.comparator, a comparator' if !options?.comparator?\n throw 'Must pass options.onInsertConflict, a function' if !options?.onInsertConflict?\n @priv = new options.strategy(options)\n @length = 0\n\n insert: (value) ->\n @priv.insert(value)\n @length += 1\n this\n\n remove: (value) ->\n @priv.remove(value)\n @length -= 1\n this\n\n clear: ->\n @priv.clear()\n @length = 0\n this\n\n contains: (value) ->\n @priv.contains(value)\n\n # Returns this set as an Array\n toArray: -> @priv.toArray()\n\n forEach: (callback, thisArg) ->\n @priv.forEachImpl(callback, this, thisArg)\n this\n\n map: (callback, thisArg) ->\n ret = []\n @forEach (value, index, self) ->\n ret.push(callback.call(thisArg, value, index, self))\n ret\n\n filter: (callback, thisArg) ->\n ret = []\n @forEach (value, index, self) ->\n ret.push(value) if callback.call(thisArg, value, index, self)\n ret\n\n every: (callback, thisArg) ->\n ret = true\n @forEach (value, index, self) ->\n ret = false if ret && !callback.call(thisArg, value, index, self)\n ret\n\n some: (callback, thisArg) ->\n ret = false\n @forEach (value, index, self) ->\n ret = true if !ret && callback.call(thisArg, value, index, self)\n ret\n\n # An iterator is similar to a C++ iterator: it points _before_ a value.\n #\n # So in this sorted set:\n #\n # | 1 | 2 | 3 | 4 | 5 |\n # ^a ^b ^c\n #\n # `a` is a pointer to the beginning of the iterator. `a.value()` returns\n # `3`. `a.previous()` returns `null`. `a.setValue()` works, if\n # `options.allowSetValue` is true.\n # \n # `b` is a pointer to the value `3`. `a.previous()` and `a.next()` both do\n # the obvious.\n #\n # `c` is a pointer to the `null` value. `c.previous()` works; `c.next()`\n # returns null. `c.setValue()` throws an exception, even if\n # `options.allowSetValue` is true.\n #\n # Iterators have `hasNext()` and `hasPrevious()` methods, too.\n #\n # Iterators are immutible. `iterator.next()` returns a new iterator.\n #\n # Iterators become invalid as soon as `insert()` or `remove()` is called.\n findIterator: (value) ->\n @priv.findIterator(value)\n\n # Finds an iterator pointing to the lowest possible value.\n beginIterator: ->\n @priv.beginIterator()\n\n # Finds an iterator pointing to the `null` value.\n endIterator: ->\n @priv.endIterator()\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/ArrayStrategy.js b/dist/SortedSet/ArrayStrategy.js index 1156b7a..3c4f9b8 100644 --- a/dist/SortedSet/ArrayStrategy.js +++ b/dist/SortedSet/ArrayStrategy.js @@ -1,8 +1,6 @@ // Generated by CoffeeScript 2.5.1 (function() { - var ArrayStrategy, Iterator, binarySearchForIndex, enums; - - enums = require('../enums'); + var ArrayStrategy, Iterator, binarySearchForIndex; Iterator = class Iterator { constructor(priv, index1) { @@ -73,7 +71,7 @@ ArrayStrategy = class ArrayStrategy { constructor(options) { this.options = options; - this.insertBehavior = this.options.insertBehavior; + this.onInsertConflict = this.options.onInsertConflict; this.comparator = this.options.comparator; this.data = []; } @@ -85,21 +83,10 @@ insert(value) { var index; index = binarySearchForIndex(this.data, value, this.comparator); - if (value !== void 0 && this.data[index] !== void 0 && this.comparator(this.data[index], value) === 0) { - switch (this.insertBehavior) { - case enums.insertBehaviors.throw: - throw 'Value already in set'; - case enums.insertBehaviors.replace: - this.data.splice(index, 1, value); - return true; - case enums.insertBehaviors.ignore: - return false; - default: - throw 'Unsupported insert behavior #{@insertBehavior}'; - } + if (this.data[index] !== void 0 && this.comparator(this.data[index], value) === 0) { + return this.data.splice(index, 1, this.onInsertConflict(this.data[index], value)); } else { - this.data.splice(index, 0, value); - return true; + return this.data.splice(index, 0, value); } } @@ -151,3 +138,5 @@ module.exports = ArrayStrategy; }).call(this); + +//# sourceMappingURL=ArrayStrategy.js.map diff --git a/dist/SortedSet/ArrayStrategy.js.map b/dist/SortedSet/ArrayStrategy.js.map new file mode 100644 index 0000000..43e76c6 --- /dev/null +++ b/dist/SortedSet/ArrayStrategy.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "ArrayStrategy.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/ArrayStrategy.coffee" + ], + "names": [], + "mappings": "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", + "sourcesContent": [ + "\nclass Iterator\n constructor: (@priv, @index) ->\n @data = @priv.data\n\n hasNext: -> @index < @data.length\n hasPrevious: -> @index > 0\n value: -> if @index < @data.length then @data[@index] else null\n setValue: (value) ->\n throw 'Must set options.allowSetValue' if !@priv.options.allowSetValue\n throw 'Cannot set value at end of set' if !@hasNext()\n @data[@index] = value\n\n next: ->\n if @index >= @data.length\n null\n else\n new Iterator(@priv, @index + 1)\n\n previous: ->\n if @index <= 0\n null\n else\n new Iterator(@priv, @index - 1)\n\nbinarySearchForIndex = (array, value, comparator) ->\n low = 0\n high = array.length\n while low < high\n mid = (low + high) >>> 1\n if comparator(array[mid], value) < 0\n low = mid + 1\n else\n high = mid\n low\n\nclass ArrayStrategy\n constructor: (@options) ->\n @onInsertConflict = @options.onInsertConflict\n @comparator = @options.comparator\n @data = []\n\n toArray: -> @data\n\n insert: (value) ->\n index = binarySearchForIndex(@data, value, @comparator)\n if @data[index] != undefined and @comparator(@data[index], value) == 0\n @data.splice(index, 1, @onInsertConflict(@data[index], value))\n else\n @data.splice(index, 0, value)\n\n remove: (value) ->\n index = binarySearchForIndex(@data, value, @comparator)\n throw 'Value not in set' if @data[index] != value\n @data.splice(index, 1)\n\n clear: ->\n @data.length = 0\n\n contains: (value) ->\n index = binarySearchForIndex(@data, value, @comparator)\n @index != @data.length && @data[index] == value\n\n forEachImpl: (callback, sortedSet, thisArg) ->\n for value, index in @data\n callback.call(thisArg, value, index, sortedSet)\n undefined\n\n findIterator: (value) ->\n index = binarySearchForIndex(@data, value, @comparator)\n new Iterator(this, index)\n\n beginIterator: -> new Iterator(this, 0)\n endIterator: -> new Iterator(this, @data.length)\n\nmodule.exports = ArrayStrategy\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/BinaryTreeIterator.js b/dist/SortedSet/BinaryTreeIterator.js index 764c1d0..5709731 100644 --- a/dist/SortedSet/BinaryTreeIterator.js +++ b/dist/SortedSet/BinaryTreeIterator.js @@ -148,3 +148,5 @@ module.exports = BinaryTreeIterator; }).call(this); + +//# sourceMappingURL=BinaryTreeIterator.js.map diff --git a/dist/SortedSet/BinaryTreeIterator.js.map b/dist/SortedSet/BinaryTreeIterator.js.map new file mode 100644 index 0000000..04a26de --- /dev/null +++ b/dist/SortedSet/BinaryTreeIterator.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "BinaryTreeIterator.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/BinaryTreeIterator.coffee" + ], + "names": [], + "mappings": "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", + "sourcesContent": [ + "descendAllTheWay = (leftOrRight, node) ->\n # Assumes node._iteratorParentNode is set\n while node[leftOrRight] isnt null\n parent = node\n node = node[leftOrRight]\n node._iteratorParentNode = parent\n node\n\nmoveCursor = (leftOrRight, node) ->\n if node[leftOrRight] isnt null\n parent = node\n node = node[leftOrRight]\n node._iteratorParentNode = parent\n rightOrLeft = if leftOrRight == 'left' then 'right' else 'left'\n node = descendAllTheWay(rightOrLeft, node)\n else\n while (parent = node._iteratorParentNode) isnt null && parent[leftOrRight] is node\n node = parent\n node = parent # either null or the correct-direction parent\n\n node\n\n# The BinaryTreeIterator actually writes to the tree: it maintains a\n# \"_iteratorParentNode\" variable on each node. Please ignore this.\nclass BinaryTreeIterator\n constructor: (@tree, @node) ->\n\n next: ->\n if @node is null\n null\n else\n node = moveCursor('right', @node)\n new BinaryTreeIterator(@tree, node)\n\n previous: ->\n if @node is null\n if @tree.root is null\n null\n else\n @tree.root._iteratorParentNode = null\n node = descendAllTheWay('right', @tree.root)\n new BinaryTreeIterator(@tree, node)\n else\n node = moveCursor('left', @node)\n if node is null\n null\n else\n new BinaryTreeIterator(@tree, node)\n\n hasNext: -> @node isnt null\n hasPrevious: -> @previous() isnt null\n value: -> if @node is null then null else @node.value\n setValue: (value) ->\n throw 'Must set options.allowSetValue' if !@tree.options.allowSetValue\n throw 'Cannot set value at end of set' if !@hasNext()\n @node.value = value\n\nBinaryTreeIterator.find = (tree, value, comparator) ->\n root = tree.root\n root?._iteratorParentNode = null\n node = root\n nextNode = null # For finding an in-between node\n while node isnt null\n cmp = comparator(value, node.value)\n if cmp == 0\n break\n else if cmp < 0\n break if node.left is null\n\n nextNode = node # If we descend all right after this until there are\n # no more right nodes, we want to return an\n # \"in-between\" iterator ... pointing here.\n node.left._iteratorParentNode = node\n node = node.left\n else\n if node.right isnt null\n node.right._iteratorParentNode = node\n node = node.right\n else\n node = nextNode\n break\n\n return new BinaryTreeIterator(tree, node)\n\nBinaryTreeIterator.left = (tree) ->\n if tree.root is null\n new BinaryTreeIterator(tree, null)\n else\n tree.root._iteratorParentNode = null\n node = descendAllTheWay('left', tree.root)\n new BinaryTreeIterator(tree, node)\n\nBinaryTreeIterator.right = (tree) ->\n new BinaryTreeIterator(tree, null)\n\nmodule.exports = BinaryTreeIterator\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/BinaryTreeStrategy.js b/dist/SortedSet/BinaryTreeStrategy.js index 0c460c8..9220bdc 100644 --- a/dist/SortedSet/BinaryTreeStrategy.js +++ b/dist/SortedSet/BinaryTreeStrategy.js @@ -1,8 +1,6 @@ // Generated by CoffeeScript 2.5.1 (function() { - var AbstractBinaryTreeStrategy, BinaryTreeStrategy, Node, binaryTreeDelete, enums, nodeAllTheWay; - - enums = require('../enums'); + var AbstractBinaryTreeStrategy, BinaryTreeStrategy, Node, binaryTreeDelete, nodeAllTheWay; AbstractBinaryTreeStrategy = require('./AbstractBinaryTreeStrategy'); @@ -54,29 +52,21 @@ super(); this.options = options; this.comparator = this.options.comparator; - this.insertBehavior = this.options.insertBehavior; + this.onInsertConflict = this.options.onInsertConflict; this.root = null; } insert(value) { - var cmp, compare, leftOrRight, parent; + var cmp, compare, leftOrRight, onInsertConflict, parent; compare = this.comparator; + onInsertConflict = this.onInsertConflict; if (this.root != null) { parent = this.root; while (true) { cmp = compare(value, parent.value); if (cmp === 0) { - switch (this.insertBehavior) { - case enums.insertBehaviors.throw: - throw 'Value already in set'; - case enums.insertBehaviors.replace: - parent.value = value; - return true; - case enums.insertBehaviors.ignore: - return false; - default: - throw 'Unsupported insert behavior #{@insertBehavior}'; - } + parent.value = onInsertConflict(parent.value, value); + return; } else { leftOrRight = cmp < 0 ? 'left' : 'right'; if (parent[leftOrRight] === null) { @@ -85,11 +75,9 @@ parent = parent[leftOrRight]; } } - parent[leftOrRight] = new Node(value); - return true; + return parent[leftOrRight] = new Node(value); } else { - this.root = new Node(value); - return true; + return this.root = new Node(value); } } @@ -102,3 +90,5 @@ module.exports = BinaryTreeStrategy; }).call(this); + +//# sourceMappingURL=BinaryTreeStrategy.js.map diff --git a/dist/SortedSet/BinaryTreeStrategy.js.map b/dist/SortedSet/BinaryTreeStrategy.js.map new file mode 100644 index 0000000..b4a3683 --- /dev/null +++ b/dist/SortedSet/BinaryTreeStrategy.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "BinaryTreeStrategy.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/BinaryTreeStrategy.coffee" + ], + "names": [], + "mappings": "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", + "sourcesContent": [ + "\nAbstractBinaryTreeStrategy = require('./AbstractBinaryTreeStrategy')\n\nclass Node\n constructor: (@value) ->\n @left = null\n @right = null\n\nnodeAllTheWay = (node, leftOrRight) ->\n while node[leftOrRight] isnt null\n node = node[leftOrRight]\n node\n\n# Returns the subtree, minus value\nbinaryTreeDelete = (node, value, comparator) ->\n throw 'Value not in set' if node is null\n\n cmp = comparator(value, node.value)\n if cmp < 0\n node.left = binaryTreeDelete(node.left, value, comparator)\n else if cmp > 0\n node.right = binaryTreeDelete(node.right, value, comparator)\n else # This is the value we want to remove\n if node.left is null && node.right is null\n node = null\n else if node.right is null\n node = node.left\n else if node.left is null\n node = node.right\n else\n nextNode = nodeAllTheWay(node.right, 'left')\n node.value = nextNode.value\n node.right = binaryTreeDelete(node.right, nextNode.value, comparator)\n\n node\n\nclass BinaryTreeStrategy extends AbstractBinaryTreeStrategy\n constructor: (@options) ->\n super()\n @comparator = @options.comparator\n @onInsertConflict = @options.onInsertConflict\n @root = null\n\n insert: (value) ->\n compare = @comparator\n onInsertConflict = @onInsertConflict\n if @root?\n parent = @root\n loop\n cmp = compare(value, parent.value)\n if cmp == 0\n parent.value = onInsertConflict(parent.value, value)\n return\n else\n leftOrRight = if cmp < 0 then 'left' else 'right'\n break if parent[leftOrRight] == null\n parent = parent[leftOrRight]\n parent[leftOrRight] = new Node(value)\n else\n @root = new Node(value)\n\n remove: (value) ->\n @root = binaryTreeDelete(@root, value, @comparator)\n\nmodule.exports = BinaryTreeStrategy\n" + ] +} \ No newline at end of file diff --git a/dist/SortedSet/RedBlackTreeStrategy.js b/dist/SortedSet/RedBlackTreeStrategy.js index 625594b..16f4682 100644 --- a/dist/SortedSet/RedBlackTreeStrategy.js +++ b/dist/SortedSet/RedBlackTreeStrategy.js @@ -73,20 +73,20 @@ return h; }; - insertInNode = function(h, value, compare) { + insertInNode = function(h, value, compare, onInsertConflict) { + var cmp; if (h === null) { return new Node(value); } //if h.left isnt null && h.left.isRed && h.right isnt null && h.right.isRed // colorFlip(h) - if (h.value === value) { - throw 'Value already in set'; + cmp = compare(value, h.value); + if (cmp === 0) { + h.value = onInsertConflict(h.value, value); + } else if (cmp < 0) { + h.left = insertInNode(h.left, value, compare, onInsertConflict); } else { - if (compare(value, h.value) < 0) { - h.left = insertInNode(h.left, value, compare); - } else { - h.right = insertInNode(h.right, value, compare); - } + h.right = insertInNode(h.right, value, compare, onInsertConflict); } if (h.right !== null && h.right.isRed && !(h.left !== null && h.left.isRed)) { h = rotateLeft(h); @@ -179,11 +179,12 @@ super(); this.options = options; this.comparator = this.options.comparator; + this.onInsertConflict = this.options.onInsertConflict; this.root = null; } insert(value) { - this.root = insertInNode(this.root, value, this.comparator); + this.root = insertInNode(this.root, value, this.comparator, this.onInsertConflict); this.root.isRed = false; // always return void 0; } @@ -199,3 +200,5 @@ }; }).call(this); + +//# sourceMappingURL=RedBlackTreeStrategy.js.map diff --git a/dist/SortedSet/RedBlackTreeStrategy.js.map b/dist/SortedSet/RedBlackTreeStrategy.js.map new file mode 100644 index 0000000..429e41c --- /dev/null +++ b/dist/SortedSet/RedBlackTreeStrategy.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "RedBlackTreeStrategy.js", + "sourceRoot": "../..", + "sources": [ + "src/SortedSet/RedBlackTreeStrategy.coffee" + ], + "names": [], + "mappings": ";AACA;AAAA,MAAA,0BAAA,EAAA,IAAA,EAAA,oBAAA,EAAA,SAAA,EAAA,WAAA,EAAA,KAAA,EAAA,YAAA,EAAA,WAAA,EAAA,YAAA,EAAA,cAAA,EAAA,aAAA,EAAA,UAAA,EAAA;;EAAA,0BAAA,GAA6B,OAAA,CAAQ,8BAAR,EAA7B;;;;;;;;;;;;;EAcM,OAAN,MAAA,KAAA;IACE,WAAa,OAAA,CAAA;MAAC,IAAC,CAAA;MACb,IAAC,CAAA,IAAD,GAAQ;MACR,IAAC,CAAA,KAAD,GAAS;MACT,IAAC,CAAA,KAAD,GAAS,KAHE;IAAA;;EADf;;EAMA,UAAA,GAAa,QAAA,CAAC,CAAD,CAAA;AACb,QAAA;IAAE,CAAA,GAAI,CAAC,CAAC;IACN,CAAC,CAAC,KAAF,GAAU,CAAC,CAAC;IACZ,CAAC,CAAC,IAAF,GAAS;IACT,CAAC,CAAC,KAAF,GAAU,CAAC,CAAC;IACZ,CAAC,CAAC,KAAF,GAAU;WACV;EANW;;EAQb,WAAA,GAAc,QAAA,CAAC,CAAD,CAAA;AACd,QAAA;IAAE,CAAA,GAAI,CAAC,CAAC;IACN,CAAC,CAAC,IAAF,GAAS,CAAC,CAAC;IACX,CAAC,CAAC,KAAF,GAAU;IACV,CAAC,CAAC,KAAF,GAAU,CAAC,CAAC;IACZ,CAAC,CAAC,KAAF,GAAU;WACV;EANY;;EAQd,SAAA,GAAY,QAAA,CAAC,CAAD,CAAA;IACV,CAAC,CAAC,KAAF,GAAU,CAAC,CAAC,CAAC;IACb,CAAC,CAAC,IAAI,CAAC,KAAP,GAAe,CAAC,CAAC,CAAC,IAAI,CAAC;IACvB,CAAC,CAAC,KAAK,CAAC,KAAR,GAAgB,CAAC,CAAC,CAAC,KAAK,CAAC;WACzB;EAJU;;EAMZ,WAAA,GAAc,QAAA,CAAC,CAAD,CAAA,EAAA;;IAEZ,SAAA,CAAU,CAAV;IACA,IAAG,CAAC,CAAC,KAAF,KAAa,IAAb,IAAqB,CAAC,CAAC,KAAK,CAAC,IAAR,KAAkB,IAAvC,IAA+C,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAA/D;MACE,CAAC,CAAC,KAAF,GAAU,WAAA,CAAY,CAAC,CAAC,KAAd;MACV,CAAA,GAAI,UAAA,CAAW,CAAX;MACJ,SAAA,CAAU,CAAV,EAHF;;WAIA;EAPY;;EASd,YAAA,GAAe,QAAA,CAAC,CAAD,CAAA,EAAA;;IAEb,SAAA,CAAU,CAAV;IACA,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,IAAP,KAAiB,IAArC,IAA6C,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAA5D;MACE,CAAA,GAAI,WAAA,CAAY,CAAZ;MACJ,SAAA,CAAU,CAAV,EAFF;;WAGA;EANa;;EAQf,YAAA,GAAe,QAAA,CAAC,CAAD,EAAI,KAAJ,EAAW,OAAX,EAAoB,gBAApB,CAAA;AACf,QAAA;IAAE,IAAG,CAAA,KAAK,IAAR;AACE,aAAO,IAAI,IAAJ,CAAS,KAAT,EADT;KAAF;;;IAME,GAAA,GAAM,OAAA,CAAQ,KAAR,EAAe,CAAC,CAAC,KAAjB;IAEN,IAAG,GAAA,KAAO,CAAV;MACE,CAAC,CAAC,KAAF,GAAU,gBAAA,CAAiB,CAAC,CAAC,KAAnB,EAA0B,KAA1B,EADZ;KAAA,MAEK,IAAG,GAAA,GAAM,CAAT;MACH,CAAC,CAAC,IAAF,GAAS,YAAA,CAAa,CAAC,CAAC,IAAf,EAAqB,KAArB,EAA4B,OAA5B,EAAqC,gBAArC,EADN;KAAA,MAAA;MAGH,CAAC,CAAC,KAAF,GAAU,YAAA,CAAa,CAAC,CAAC,KAAf,EAAsB,KAAtB,EAA6B,OAA7B,EAAsC,gBAAtC,EAHP;;IAKL,IAAG,CAAC,CAAC,KAAF,KAAa,IAAb,IAAqB,CAAC,CAAC,KAAK,CAAC,KAA7B,IAAsC,CAAC,CAAC,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA5B,CAA1C;MACE,CAAA,GAAI,UAAA,CAAW,CAAX,EADN;;IAGA,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA3B,IAAoC,CAAC,CAAC,IAAI,CAAC,IAAP,KAAiB,IAArD,IAA6D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAA5E;MACE,CAAA,GAAI,WAAA,CAAY,CAAZ,EADN;KAlBF;;IAsBE,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA3B,IAAoC,CAAC,CAAC,KAAF,KAAa,IAAjD,IAAyD,CAAC,CAAC,KAAK,CAAC,KAApE;MACE,SAAA,CAAU,CAAV,EADF;;WAGA;EA1Ba;;EA4Bf,WAAA,GAAc,QAAA,CAAC,CAAD,CAAA;AACZ,WAAM,CAAC,CAAC,IAAF,KAAY,IAAlB;MACE,CAAA,GAAI,CAAC,CAAC;IADR;WAEA;EAHY;;EAKd,KAAA,GAAQ,QAAA,CAAC,CAAD,CAAA,EAAA;;IAEN,IAAG,CAAC,CAAC,KAAF,KAAa,IAAb,IAAqB,CAAC,CAAC,KAAK,CAAC,KAAhC;MACE,CAAA,GAAI,UAAA,CAAW,CAAX,EADN;KADF;;IAKE,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA3B,IAAoC,CAAC,CAAC,IAAI,CAAC,IAAP,KAAiB,IAArD,IAA6D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAA5E;MACE,CAAA,GAAI,WAAA,CAAY,CAAZ,EADN;KALF;;IASE,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA3B,IAAoC,CAAC,CAAC,KAAF,KAAa,IAAjD,IAAyD,CAAC,CAAC,KAAK,CAAC,KAApE;MACE,SAAA,CAAU,CAAV,EADF;;WAGA;EAbM;;EAeR,aAAA,GAAgB,QAAA,CAAC,CAAD,CAAA;IACd,IAAG,CAAC,CAAC,IAAF,KAAU,IAAb;AACE,aAAO,KADT;;IAGA,IAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAR,IAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAP,KAAiB,IAAjB,IAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAtC,CAArB;MACE,CAAA,GAAI,WAAA,CAAY,CAAZ,EADN;;IAGA,CAAC,CAAC,IAAF,GAAS,aAAA,CAAc,CAAC,CAAC,IAAhB;WAET,KAAA,CAAM,CAAN;EATc;;EAWhB,cAAA,GAAiB,QAAA,CAAC,CAAD,EAAI,KAAJ,EAAW,OAAX,CAAA;IACf,IAA4B,CAAA,KAAK,IAAjC;MAAA,MAAM,mBAAN;;IAEA,IAAG,CAAC,CAAC,KAAF,KAAa,KAAb,IAAsB,OAAA,CAAQ,KAAR,EAAe,CAAC,CAAC,KAAjB,CAAA,GAA0B,CAAnD;MACE,IAA4B,CAAC,CAAC,IAAF,KAAU,IAAtC;QAAA,MAAM,mBAAN;;MACA,IAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAR,IAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAP,KAAiB,IAAjB,IAAyB,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAtC,CAArB;QACE,CAAA,GAAI,WAAA,CAAY,CAAZ,EADN;;MAEA,CAAC,CAAC,IAAF,GAAS,cAAA,CAAe,CAAC,CAAC,IAAjB,EAAuB,KAAvB,EAA8B,OAA9B,EAJX;KAAA,MAAA;MAME,IAAG,CAAC,CAAC,IAAF,KAAY,IAAZ,IAAoB,CAAC,CAAC,IAAI,CAAC,KAA9B;QACE,CAAA,GAAI,WAAA,CAAY,CAAZ,EADN;;MAGA,IAAG,CAAC,CAAC,KAAF,KAAW,IAAd;QACE,IAAG,KAAA,KAAS,CAAC,CAAC,KAAd;AACE,iBAAO,KADT;SAAA,MAAA;UAGE,MAAM,mBAHR;SADF;;MAMA,IAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAT,IAAkB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAR,KAAkB,IAAlB,IAA0B,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAxC,CAAtB;QACE,CAAA,GAAI,YAAA,CAAa,CAAb,EADN;;MAEA,IAAG,KAAA,KAAS,CAAC,CAAC,KAAd;QACE,CAAC,CAAC,KAAF,GAAU,WAAA,CAAY,CAAC,CAAC,KAAd,CAAoB,CAAC;QAC/B,CAAC,CAAC,KAAF,GAAU,aAAA,CAAc,CAAC,CAAC,KAAhB,EAFZ;OAAA,MAAA;QAIE,CAAC,CAAC,KAAF,GAAU,cAAA,CAAe,CAAC,CAAC,KAAjB,EAAwB,KAAxB,EAA+B,OAA/B,EAJZ;OAjBF;;IAuBA,IAAgB,CAAA,KAAO,IAAvB;MAAA,CAAA,GAAI,KAAA,CAAM,CAAN,EAAJ;;WAEA;EA5Be;;EA8BjB,MAAM,CAAC,OAAP,GAAuB,uBAAN,MAAA,qBAAA,QAAmC,2BAAnC;IACf,WAAa,QAAA,CAAA;;MAAC,IAAC,CAAA;MAEb,IAAC,CAAA,UAAD,GAAc,IAAC,CAAA,OAAO,CAAC;MACvB,IAAC,CAAA,gBAAD,GAAoB,IAAC,CAAA,OAAO,CAAC;MAC7B,IAAC,CAAA,IAAD,GAAQ;IAJG;;IAMb,MAAQ,CAAC,KAAD,CAAA;MACN,IAAC,CAAA,IAAD,GAAQ,YAAA,CAAa,IAAC,CAAA,IAAd,EAAoB,KAApB,EAA2B,IAAC,CAAA,UAA5B,EAAwC,IAAC,CAAA,gBAAzC;MACR,IAAC,CAAA,IAAI,CAAC,KAAN,GAAc,MADlB;aAEI;IAHM;;IAKR,MAAQ,CAAC,KAAD,CAAA;MACN,IAAC,CAAA,IAAD,GAAQ,cAAA,CAAe,IAAC,CAAA,IAAhB,EAAsB,KAAtB,EAA6B,IAAC,CAAA,UAA9B;MACR,IAAuB,IAAC,CAAA,IAAD,KAAW,IAAlC;QAAA,IAAC,CAAA,IAAI,CAAC,KAAN,GAAc,MAAd;;aACA;IAHM;;EAZO;AApJjB", + "sourcesContent": [ + "\nAbstractBinaryTreeStrategy = require('./AbstractBinaryTreeStrategy')\n\n# An implementation of Left-Leaning Red-Black trees.\n#\n# It's copied from http://www.cs.princeton.edu/~rs/talks/LLRB/LLRB.pdf.\n# It's practically a copy-paste job, minus the semicolons. missing bits were\n# filled in with hints from\n# http://www.teachsolaisgames.com/articles/balanced_left_leaning.html\n#\n# Here are some differences:\n# * This isn't a map structure: it's just a tree. There are no keys: the\n# comparator applies to the values.\n# * We use the passed comparator.\n\nclass Node\n constructor: (@value) ->\n @left = null\n @right = null\n @isRed = true # null nodes -- leaves -- are black\n\nrotateLeft = (h) ->\n x = h.right\n h.right = x.left\n x.left = h\n x.isRed = h.isRed\n h.isRed = true\n x\n\nrotateRight = (h) ->\n x = h.left\n h.left = x.right\n x.right = h\n x.isRed = h.isRed\n h.isRed = true\n x\n\ncolorFlip = (h) ->\n h.isRed = !h.isRed\n h.left.isRed = !h.left.isRed\n h.right.isRed = !h.right.isRed\n undefined\n\nmoveRedLeft = (h) ->\n #throw 'Preconditions failed' if !(!h.left.isRed && !h.left.left?.isRed)\n colorFlip(h)\n if h.right isnt null && h.right.left isnt null && h.right.left.isRed\n h.right = rotateRight(h.right)\n h = rotateLeft(h)\n colorFlip(h)\n h\n\nmoveRedRight = (h) ->\n #throw 'Preconditions failed' if !(!h.right.isRed && !h.right.left?.isRed)\n colorFlip(h)\n if h.left isnt null && h.left.left isnt null && h.left.left.isRed\n h = rotateRight(h)\n colorFlip(h)\n h\n\ninsertInNode = (h, value, compare, onInsertConflict) ->\n if h is null\n return new Node(value)\n\n #if h.left isnt null && h.left.isRed && h.right isnt null && h.right.isRed\n # colorFlip(h)\n\n cmp = compare(value, h.value)\n\n if cmp == 0\n h.value = onInsertConflict(h.value, value)\n else if cmp < 0\n h.left = insertInNode(h.left, value, compare, onInsertConflict)\n else\n h.right = insertInNode(h.right, value, compare, onInsertConflict)\n\n if h.right isnt null && h.right.isRed && !(h.left isnt null && h.left.isRed)\n h = rotateLeft(h)\n\n if h.left isnt null && h.left.isRed && h.left.left isnt null && h.left.left.isRed\n h = rotateRight(h)\n\n # Put this here -- I couldn't get the whole thing to work otherwise :(\n if h.left isnt null && h.left.isRed && h.right isnt null && h.right.isRed\n colorFlip(h)\n\n h\n\nfindMinNode = (h) ->\n while h.left isnt null\n h = h.left\n h\n\nfixUp = (h) ->\n # Fix right-leaning red nodes\n if h.right isnt null && h.right.isRed\n h = rotateLeft(h)\n\n # Handle a 4-node that traverses down the left\n if h.left isnt null && h.left.isRed && h.left.left isnt null && h.left.left.isRed\n h = rotateRight(h)\n\n # split 4-nodes\n if h.left isnt null && h.left.isRed && h.right isnt null && h.right.isRed\n colorFlip(h)\n\n h\n\nremoveMinNode = (h) ->\n if h.left is null\n return null\n\n if !h.left.isRed && !(h.left.left isnt null && h.left.left.isRed)\n h = moveRedLeft(h)\n\n h.left = removeMinNode(h.left)\n\n fixUp(h)\n\nremoveFromNode = (h, value, compare) ->\n throw 'Value not in set' if h is null\n\n if h.value isnt value && compare(value, h.value) < 0\n throw 'Value not in set' if h.left is null\n if !h.left.isRed && !(h.left.left isnt null && h.left.left.isRed)\n h = moveRedLeft(h)\n h.left = removeFromNode(h.left, value, compare)\n else\n if h.left isnt null && h.left.isRed\n h = rotateRight(h)\n\n if h.right is null\n if value is h.value\n return null # leaf node; LLRB assures no left value here\n else\n throw 'Value not in set'\n\n if !h.right.isRed && !(h.right.left isnt null && h.right.left.isRed)\n h = moveRedRight(h)\n if value is h.value\n h.value = findMinNode(h.right).value\n h.right = removeMinNode(h.right)\n else\n h.right = removeFromNode(h.right, value, compare)\n\n h = fixUp(h) if h isnt null\n\n h\n\nmodule.exports = class RedBlackTreeStrategy extends AbstractBinaryTreeStrategy\n constructor: (@options) ->\n super()\n @comparator = @options.comparator\n @onInsertConflict = @options.onInsertConflict\n @root = null\n\n insert: (value) ->\n @root = insertInNode(@root, value, @comparator, @onInsertConflict)\n @root.isRed = false # always\n undefined\n\n remove: (value) ->\n @root = removeFromNode(@root, value, @comparator)\n @root.isRed = false if @root isnt null\n undefined\n" + ] +} \ No newline at end of file diff --git a/dist/enums.js b/dist/enums.js deleted file mode 100644 index 2f4a13d..0000000 --- a/dist/enums.js +++ /dev/null @@ -1,11 +0,0 @@ -// Generated by CoffeeScript 2.5.1 -(function() { - module.exports = { - insertBehaviors: { - throw: 'INSERT_THROW', - replace: 'INSERT_REPLACE', - ignore: 'INSERT_IGNORE' - } - }; - -}).call(this); diff --git a/dist/insertConflictResolvers.js b/dist/insertConflictResolvers.js new file mode 100644 index 0000000..24aeb6d --- /dev/null +++ b/dist/insertConflictResolvers.js @@ -0,0 +1,17 @@ +// Generated by CoffeeScript 2.5.1 +(function() { + module.exports.throw = function(oldValue, newValue) { + throw 'Value already in set'; + }; + + module.exports.replace = function(oldValue, newValue) { + return newValue; + }; + + module.exports.ignore = function(oldValue, newValue) { + return oldValue; + }; + +}).call(this); + +//# sourceMappingURL=insertConflictResolvers.js.map diff --git a/dist/insertConflictResolvers.js.map b/dist/insertConflictResolvers.js.map new file mode 100644 index 0000000..db23e48 --- /dev/null +++ b/dist/insertConflictResolvers.js.map @@ -0,0 +1,13 @@ +{ + "version": 3, + "file": "insertConflictResolvers.js", + "sourceRoot": "..", + "sources": [ + "src/insertConflictResolvers.coffee" + ], + "names": [], + "mappings": ";AACA;EAAA,MAAM,CAAC,OAAO,CAAC,KAAf,GAAuB,QAAA,CAAC,QAAD,EAAW,QAAX,CAAA;IAAwB,MAAM;EAA9B;;EACvB,MAAM,CAAC,OAAO,CAAC,OAAf,GAAyB,QAAA,CAAC,QAAD,EAAW,QAAX,CAAA;WAAwB;EAAxB;;EACzB,MAAM,CAAC,OAAO,CAAC,MAAf,GAAwB,QAAA,CAAC,QAAD,EAAW,QAAX,CAAA;WAAwB;EAAxB;AAFxB", + "sourcesContent": [ + "\nmodule.exports.throw = (oldValue, newValue) -> throw 'Value already in set'\nmodule.exports.replace = (oldValue, newValue) -> newValue\nmodule.exports.ignore = (oldValue, newValue) -> oldValue\n" + ] +} \ No newline at end of file diff --git a/package.json b/package.json index b22f904..859436c 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "./dist/SortedSet.js", "scripts": { "test": "npm run dist && mocha --extension coffee", - "dist": "coffee --output ./dist src" + "dist": "coffee -m --output ./dist src" }, "repository": { "type": "git", diff --git a/src/SortedSet.coffee b/src/SortedSet.coffee index 563f751..f8426a1 100644 --- a/src/SortedSet.coffee +++ b/src/SortedSet.coffee @@ -2,19 +2,22 @@ AbstractSortedSet = require('./SortedSet/AbstractSortedSet') ArrayStrategy = require('./SortedSet/ArrayStrategy') BinaryTreeStrategy = require('./SortedSet/BinaryTreeStrategy') RedBlackTreeStrategy = require('./SortedSet/RedBlackTreeStrategy') -enums = require('./enums') +insertConflictResolvers = require('./insertConflictResolvers') class SortedSet extends AbstractSortedSet constructor: (options) -> options ||= {} options.strategy ||= RedBlackTreeStrategy options.comparator ||= (a, b) -> (a || 0) - (b || 0) - options.insertBehavior ||= enums.insertBehaviors.throw + options.onInsertConflict ||= insertConflictResolvers.throw super(options) SortedSet.ArrayStrategy = ArrayStrategy SortedSet.BinaryTreeStrategy = BinaryTreeStrategy SortedSet.RedBlackTreeStrategy = RedBlackTreeStrategy -SortedSet.insertBehaviors = enums.insertBehaviors + +SortedSet.onInsertConflictThrow = insertConflictResolvers.throw +SortedSet.onInsertConflictReplace = insertConflictResolvers.replace +SortedSet.onInsertConflictIgnore = insertConflictResolvers.ignore module.exports = SortedSet diff --git a/src/SortedSet/AbstractSortedSet.coffee b/src/SortedSet/AbstractSortedSet.coffee index 162f5c7..effdb4c 100644 --- a/src/SortedSet/AbstractSortedSet.coffee +++ b/src/SortedSet/AbstractSortedSet.coffee @@ -2,7 +2,7 @@ module.exports = class AbstractSortedSet constructor: (options) -> throw 'Must pass options.strategy, a strategy' if !options?.strategy? throw 'Must pass options.comparator, a comparator' if !options?.comparator? - throw 'Must pass options.insertBehavior, a number' if !options?.insertBehavior? + throw 'Must pass options.onInsertConflict, a function' if !options?.onInsertConflict? @priv = new options.strategy(options) @length = 0 diff --git a/src/SortedSet/ArrayStrategy.coffee b/src/SortedSet/ArrayStrategy.coffee index dd04d5c..722a2b5 100644 --- a/src/SortedSet/ArrayStrategy.coffee +++ b/src/SortedSet/ArrayStrategy.coffee @@ -1,6 +1,4 @@ -enums = require('../enums'); - class Iterator constructor: (@priv, @index) -> @data = @priv.data @@ -38,7 +36,7 @@ binarySearchForIndex = (array, value, comparator) -> class ArrayStrategy constructor: (@options) -> - @insertBehavior = @options.insertBehavior + @onInsertConflict = @options.onInsertConflict @comparator = @options.comparator @data = [] @@ -46,20 +44,10 @@ class ArrayStrategy insert: (value) -> index = binarySearchForIndex(@data, value, @comparator) - if value != undefined and @data[index] != undefined and @comparator(@data[index], value) == 0 - switch @insertBehavior - when enums.insertBehaviors.throw - throw 'Value already in set' - when enums.insertBehaviors.replace - @data.splice(index, 1, value) - return true - when enums.insertBehaviors.ignore - return false - else - throw 'Unsupported insert behavior #{@insertBehavior}' + if @data[index] != undefined and @comparator(@data[index], value) == 0 + @data.splice(index, 1, @onInsertConflict(@data[index], value)) else @data.splice(index, 0, value) - return true remove: (value) -> index = binarySearchForIndex(@data, value, @comparator) diff --git a/src/SortedSet/BinaryTreeStrategy.coffee b/src/SortedSet/BinaryTreeStrategy.coffee index aa3fd0f..6666657 100644 --- a/src/SortedSet/BinaryTreeStrategy.coffee +++ b/src/SortedSet/BinaryTreeStrategy.coffee @@ -1,4 +1,4 @@ -enums = require('../enums') + AbstractBinaryTreeStrategy = require('./AbstractBinaryTreeStrategy') class Node @@ -38,35 +38,26 @@ class BinaryTreeStrategy extends AbstractBinaryTreeStrategy constructor: (@options) -> super() @comparator = @options.comparator - @insertBehavior = @options.insertBehavior + @onInsertConflict = @options.onInsertConflict @root = null insert: (value) -> compare = @comparator + onInsertConflict = @onInsertConflict if @root? parent = @root loop cmp = compare(value, parent.value) if cmp == 0 - switch @insertBehavior - when enums.insertBehaviors.throw - throw 'Value already in set' - when enums.insertBehaviors.replace - parent.value = value - return true - when enums.insertBehaviors.ignore - return false - else - throw 'Unsupported insert behavior #{@insertBehavior}' + parent.value = onInsertConflict(parent.value, value) + return else leftOrRight = if cmp < 0 then 'left' else 'right' break if parent[leftOrRight] == null parent = parent[leftOrRight] parent[leftOrRight] = new Node(value) - return true else @root = new Node(value) - return true remove: (value) -> @root = binaryTreeDelete(@root, value, @comparator) diff --git a/src/SortedSet/RedBlackTreeStrategy.coffee b/src/SortedSet/RedBlackTreeStrategy.coffee index 29d5b4e..2b0799d 100644 --- a/src/SortedSet/RedBlackTreeStrategy.coffee +++ b/src/SortedSet/RedBlackTreeStrategy.coffee @@ -1,3 +1,4 @@ + AbstractBinaryTreeStrategy = require('./AbstractBinaryTreeStrategy') # An implementation of Left-Leaning Red-Black trees. @@ -57,20 +58,21 @@ moveRedRight = (h) -> colorFlip(h) h -insertInNode = (h, value, compare) -> +insertInNode = (h, value, compare, onInsertConflict) -> if h is null return new Node(value) #if h.left isnt null && h.left.isRed && h.right isnt null && h.right.isRed # colorFlip(h) - if h.value is value - throw 'Value already in set' + cmp = compare(value, h.value) + + if cmp == 0 + h.value = onInsertConflict(h.value, value) + else if cmp < 0 + h.left = insertInNode(h.left, value, compare, onInsertConflict) else - if compare(value, h.value) < 0 - h.left = insertInNode(h.left, value, compare) - else - h.right = insertInNode(h.right, value, compare) + h.right = insertInNode(h.right, value, compare, onInsertConflict) if h.right isnt null && h.right.isRed && !(h.left isnt null && h.left.isRed) h = rotateLeft(h) @@ -149,10 +151,11 @@ module.exports = class RedBlackTreeStrategy extends AbstractBinaryTreeStrategy constructor: (@options) -> super() @comparator = @options.comparator + @onInsertConflict = @options.onInsertConflict @root = null insert: (value) -> - @root = insertInNode(@root, value, @comparator) + @root = insertInNode(@root, value, @comparator, @onInsertConflict) @root.isRed = false # always undefined diff --git a/src/enums.coffee b/src/enums.coffee deleted file mode 100644 index 4d5bb97..0000000 --- a/src/enums.coffee +++ /dev/null @@ -1,8 +0,0 @@ - -module.exports = { - insertBehaviors: { - throw: 'INSERT_THROW', - replace: 'INSERT_REPLACE', - ignore: 'INSERT_IGNORE', - }, -} diff --git a/src/insertConflictResolvers.coffee b/src/insertConflictResolvers.coffee new file mode 100644 index 0000000..200a751 --- /dev/null +++ b/src/insertConflictResolvers.coffee @@ -0,0 +1,4 @@ + +module.exports.throw = (oldValue, newValue) -> throw 'Value already in set' +module.exports.replace = (oldValue, newValue) -> newValue +module.exports.ignore = (oldValue, newValue) -> oldValue diff --git a/test/SortedSet/AbstractSortedSetSpec.coffee b/test/SortedSet/AbstractSortedSetSpec.coffee index df566da..f3378ca 100644 --- a/test/SortedSet/AbstractSortedSetSpec.coffee +++ b/test/SortedSet/AbstractSortedSetSpec.coffee @@ -1,5 +1,5 @@ require('../test_helper') -enums = require('../../dist/enums') +insertConflictResolvers = require('../../dist/insertConflictResolvers') AbstractSortedSet = require('../../dist/SortedSet/AbstractSortedSet') numberCompare = (a, b) -> a - b @@ -31,7 +31,7 @@ describe 'AbstractSortedSet', -> set = new AbstractSortedSet comparator: numberCompare strategy: MockStrategy - insertBehavior: enums.insertBehaviors.throw + onInsertConflict: insertConflictResolvers.throw it 'should pass the options to the strategy', -> expect(strategy.options.comparator).to.eq(numberCompare) diff --git a/test/SortedSet/RedBlackTreeStrategySpec.coffee b/test/SortedSet/RedBlackTreeStrategySpec.coffee index b1b6508..90b8d93 100644 --- a/test/SortedSet/RedBlackTreeStrategySpec.coffee +++ b/test/SortedSet/RedBlackTreeStrategySpec.coffee @@ -2,4 +2,4 @@ require('../test_helper') RedBlackTreeStrategy = require('../../dist/SortedSet/RedBlackTreeStrategy') StrategyHelper = require('../helpers/StrategyHelper') -# StrategyHelper.describeStrategy('Left-leaning red-black tree-based strategy', RedBlackTreeStrategy) +StrategyHelper.describeStrategy('Left-leaning red-black tree-based strategy', RedBlackTreeStrategy) diff --git a/test/helpers/StrategyHelper.coffee b/test/helpers/StrategyHelper.coffee index 005719c..27ac290 100644 --- a/test/helpers/StrategyHelper.coffee +++ b/test/helpers/StrategyHelper.coffee @@ -1,5 +1,5 @@ -enums = require '../../dist/enums' +insertConflictResolvers = require '../../dist/insertConflictResolvers' numberComparator = (a, b) -> a - b @@ -181,12 +181,12 @@ module.exports = iterator = priv.endIterator() expect(-> iterator.setValue(2.5)).to.throw() - describe 'with throw insert behavior', -> + describe 'with throw behavior on insert conflict', -> beforeEach -> comparator = (a, b) -> a.v - b.v - insertBehavior = enums.insertBehaviors.throw - priv = new strategy({comparator, insertBehavior}) + onInsertConflict = insertConflictResolvers.throw + priv = new strategy({comparator, onInsertConflict}) priv.insert({ v: 1, q: 'a' }) priv.insert({ v: 2, q: 'b' }) @@ -196,30 +196,28 @@ module.exports = catch err expect(err).to.eq('Value already in set') - describe 'with replace insert behavior', -> + describe 'with replace behavior on insert conflict', -> beforeEach -> comparator = (a, b) -> a.v - b.v - insertBehavior = enums.insertBehaviors.replace - priv = new strategy({comparator, insertBehavior}) + onInsertConflict = insertConflictResolvers.replace + priv = new strategy({comparator, onInsertConflict}) priv.insert({ v: 1, q: 'a' }) priv.insert({ v: 2, q: 'b' }) it 'should replace a matching element with the new element', -> - result = priv.insert({ v: 1, q: 'c' }) - expect(result).to.eq(true) + priv.insert({ v: 1, q: 'c' }) expect(priv.toArray()).to.deep.eq([{v: 1, q: 'c'}, {v: 2, q: 'b'}]) - describe 'with ignore insert behavior', -> + describe 'with ignore behavior on insert conflict', -> beforeEach -> comparator = (a, b) -> a.v - b.v - insertBehavior = enums.insertBehaviors.ignore - priv = new strategy({comparator, insertBehavior}) + onInsertConflict = insertConflictResolvers.ignore + priv = new strategy({comparator, onInsertConflict}) priv.insert({ v: 1, q: 'a' }) priv.insert({ v: 2, q: 'b' }) it 'should ignore the new element when inserting an element that matches another ', -> - result = priv.insert({ v: 1, q: 'c' }) - expect(result).to.eq(false) + priv.insert({ v: 1, q: 'c' }) expect(priv.toArray()).to.deep.eq([{v: 1, q: 'a'}, {v: 2, q: 'b'}])