Files
meteor/packages/binary-heap/binary-heap-tests.js
2018-07-18 08:07:22 -07:00

173 lines
4.2 KiB
JavaScript

import { MaxHeap } from './max-heap.js';
import { MinMaxHeap } from './min-max-heap.js';
// Based on underscore implementation (Fisher-Yates shuffle)
const shuffle = arr => {
let j = 0;
let temp = null;
for (let i = arr.length - 1; i > 0; i -= 1) {
j = Math.floor(Math.random() * (i + 1));
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
return arr;
};
// Based on underscore implementation
const range = (start, stop, step = 1) => {
if (stop == null) {
stop = start || 0;
start = 0;
}
const length = Math.max(Math.ceil((stop - start) / step), 0);
const range = Array(length);
for (let idx = 0; idx < length; idx++, start += step) {
range[idx] = start;
}
return range;
};
Tinytest.add("binary-heap - simple max-heap tests", test => {
const h = new MaxHeap((a, b) => a - b);
h.set("a", 1);
h.set("b", 233);
h.set("c", -122);
h.set("d", 0);
h.set("e", 0);
test.equal(h.size(), 5);
test.equal(h.maxElementId(), "b");
test.equal(h.get("b"), 233);
h.remove("b");
test.equal(h.size(), 4);
test.equal(h.maxElementId(), "a");
h.set("e", 44);
test.equal(h.maxElementId(), "e");
test.equal(h.get("b"), null);
test.isTrue(h.has("a"));
test.isFalse(h.has("dd"));
h.clear();
test.isFalse(h.has("a"));
test.equal(h.size(), 0);
test.equal(h.setDefault("a", 12345), 12345);
test.equal(h.setDefault("a", 55555), 12345);
test.equal(h.size(), 1);
test.equal(h.maxElementId(), "a");
});
Tinytest.add("binary-heap - big test for max-heap", test => {
const positiveNumbers = shuffle(range(1, 41));
const negativeNumbers = shuffle(range(-1, -41, -1));
const allNumbers = [...negativeNumbers, ...positiveNumbers];
const heap = new MaxHeap((a, b) => a - b);
const output = [];
allNumbers.forEach(n => heap.set(n, n));
allNumbers.forEach(() => {
const maxId = heap.maxElementId();
output.push(heap.get(maxId));
heap.remove(maxId);
});
allNumbers.sort((a, b) => b - a);
test.equal(output, allNumbers);
});
Tinytest.add("binary-heap - min-max heap tests", test => {
const h = new MinMaxHeap((a, b) => a - b);
h.set("a", 1);
h.set("b", 233);
h.set("c", -122);
h.set("d", 0);
h.set("e", 0);
test.equal(h.size(), 5);
test.equal(h.maxElementId(), "b");
test.equal(h.get("b"), 233);
test.equal(h.minElementId(), "c");
h.remove("b");
test.equal(h.size(), 4);
test.equal(h.minElementId(), "c");
h.set("e", -123);
test.equal(h.minElementId(), "e");
test.equal(h.get("b"), null);
test.isTrue(h.has("a"));
test.isFalse(h.has("dd"));
h.clear();
test.isFalse(h.has("a"));
test.equal(h.size(), 0);
test.equal(h.setDefault("a", 12345), 12345);
test.equal(h.setDefault("a", 55555), 12345);
test.equal(h.size(), 1);
test.equal(h.maxElementId(), "a");
test.equal(h.minElementId(), "a");
});
Tinytest.add("binary-heap - big test for min-max-heap", test => {
const N = 500;
const positiveNumbers = shuffle(range(1, N + 1));
const negativeNumbers = shuffle(range(-1, -N - 1, -1));
const allNumbers = [...positiveNumbers, ...negativeNumbers];
const heap = new MinMaxHeap((a, b) => a - b);
let output = [];
const initialSets = [...allNumbers];
allNumbers.forEach(n => {
heap.set(n, n);
heap._selfCheck();
heap._minHeap._selfCheck();
});
shuffle(allNumbers);
const secondarySets = [...allNumbers];
allNumbers.forEach(n => {
heap.set(-n, n);
heap._selfCheck();
heap._minHeap._selfCheck();
});
allNumbers.forEach(() => {
const minId = heap.minElementId();
output.push(heap.get(minId));
heap.remove(minId);
heap._selfCheck(); heap._minHeap._selfCheck();
});
test.equal(heap.size(), 0);
allNumbers.sort((a, b) => a - b);
const initialTestText = `initial sets: ${initialSets.toString()}` +
`; secondary sets: ${secondarySets.toString()}`;
test.equal(output, allNumbers, initialTestText);
initialSets.forEach(n => heap.set(n, n));
secondarySets.forEach(n => heap.set(-n, n));
allNumbers.sort((a, b) => b - a);
output = [];
allNumbers.forEach(() => {
const maxId = heap.maxElementId();
output.push(heap.get(maxId));
heap.remove(maxId);
heap._selfCheck(); heap._minHeap._selfCheck();
});
test.equal(output, allNumbers, initialTestText);
});