Merge Sort: Continuation passing style
by Devin Samarin
HTML
<div class="questionbox">
<div class="question">
What do you like better? <span id="progress">1/1</span>
</div>
<div class="answers">
<a href="#" id="a1">Apple</a>
<a href="#" id="a2">Mango</a>
</div>
</div>
<div class="output"><ol id="list"></ol></div>
CSS
body {
font: 16pt sans-serif;
}
.questionbox {
background: white;
padding: 1em;
}
.question {
border: 1px solid grey;
padding: 1em;
}
.answers {
display: flex;
}
.answers a {
display: block;
flex-grow: 1;
text-align: center;
color: black;
text-decoration: none;
padding: 1em;
background: black;
color: white;
}
.answers a:hover {
background: grey;
}
JavaScript
var array = [
'Bison',
'Dolphin',
'Eagle',
'Pony',
'Ape',
'Lobster',
'Monkey',
'Cow',
'Deer',
'Duck',
'Rabbit',
'Spider',
'Wolf',
'Turkey',
'Lion',
'Pig',
'Snake',
'Shark',
'Bird',
'Bear',
'Fish',
'Chicken',
'Horse',
'Cat',
'Dog'
];
function NumberOfComparisons(n) {
const ceil = Math.ceil(Math.log(n) / Math.log(2));
return n * ceil - Math.pow(2, ceil) + 1;
}
function MergeSort(array, compare, callback) {
if (array.length < 2) {
callback(array);
} else {
var middle = Math.floor(array.length / 2);
MergeSort(array.slice(0, middle), compare, function(left) {
MergeSort(array.slice(middle, array.length), compare, function(right) {
Merge(left, right, compare, callback);
});
});
}
}
function Merge(left, right, compare, callback) {
var result = [];
(function next() {
if (left.length && right.length) {
compare(left[0], right[0], function(leftfirst) {
if (leftfirst) {
result.push(left.shift());
} else {
result.push(right.shift());
}
next();
});
} else {
while (left.length)
result.push(left.shift());
while (right.length)
result.push(right.shift());
callback(result);
}
}());
}
let ComparisonsMade = 0;
MergeSort(array, function(left, right, callback) {
const a1 = document.getElementById('a1');
const a2 = document.getElementById('a2');
const answersbox = a1.parentNode;
const progress = document.getElementById('progress');
a1.textContent = left;
a2.textContent = right;
progress.textContent = (ComparisonsMade++) + '/' + NumberOfComparisons(array.length);
answersbox.addEventListener('click', function click(event) {
const target = event.target;
if (target === a1 || target === a2) {
answersbox.removeEventListener('click', click);
callback(target === a1);
} else {
console.log("Error")
}
});
}, function(list) {
const ol = document.getElementById('list');
const progress = document.getElementById('progress');
...