198 lines
5.6 KiB
JavaScript
198 lines
5.6 KiB
JavaScript
const errorMsg = "No link found; unable to proceed";
|
|
|
|
function isFirstElementGreater(links, element1, element2) {
|
|
const relevantComparisons = links.filter(
|
|
(link) =>
|
|
(link.source == element1.name && link.target == element2.name) ||
|
|
(link.source == element2.name && link.target == element1.name)
|
|
);
|
|
if (relevantComparisons.length == 0) {
|
|
let answer = {
|
|
foundAnswer: false,
|
|
error: errorMsg,
|
|
};
|
|
return answer;
|
|
} else {
|
|
const firstLink = relevantComparisons[0];
|
|
const firstElementFirst =
|
|
firstLink.source == element1.name && firstLink.target == element2.name
|
|
? true
|
|
: false;
|
|
const distanceIsGreaterThanOne = Number(firstLink.distance) > 1;
|
|
const isFirstElementFirst =
|
|
(firstElementFirst && !distanceIsGreaterThanOne) ||
|
|
(!firstElementFirst && distanceIsGreaterThanOne);
|
|
let answer = {
|
|
foundAnswer: true,
|
|
isFirstElementFirst,
|
|
errorMsg,
|
|
};
|
|
return answer;
|
|
}
|
|
}
|
|
|
|
function merge(links, left, right) {
|
|
let sortedArr = [];
|
|
while (left.length && right.length) {
|
|
// insert the biggest element to the sortedArr
|
|
let getComparisonAnswer = isFirstElementGreater(links, left[0], right[0]);
|
|
if (getComparisonAnswer.foundAnswer == false) {
|
|
let result = {
|
|
finishedMerge: false,
|
|
uncomparedElements: [left[0], right[0]],
|
|
errorMsg: errorMsg,
|
|
};
|
|
return result;
|
|
} else if (getComparisonAnswer.foundAnswer == true) {
|
|
if (getComparisonAnswer.isFirstElementFirst == true) {
|
|
// left[0] > right[0]
|
|
// note that we can order from smallest to largest or the reverse
|
|
// ; I forget which one this is.
|
|
sortedArr.push(right.shift());
|
|
} else {
|
|
sortedArr.push(left.shift());
|
|
}
|
|
}
|
|
}
|
|
|
|
// use spread operator and create a new array, combining the three arrays
|
|
let result = {
|
|
finishedMerge: true,
|
|
orderedList: [...sortedArr, ...left, ...right],
|
|
// if they don't have the same size, the remaining ones will be greater than the ones before
|
|
};
|
|
return result;
|
|
}
|
|
|
|
export function mergeSortInner({ recursiveInput, links }) {
|
|
if (recursiveInput.bottleneckedByComparison == true) {
|
|
let result = {
|
|
recursiveInput: {
|
|
list: recursiveInput.list,
|
|
bottleneckedByComparison: true,
|
|
uncomparedElements: recursiveInput.uncomparedElements,
|
|
},
|
|
links: links,
|
|
};
|
|
return result;
|
|
}
|
|
const half = recursiveInput.list.length / 2;
|
|
|
|
// the base case is list length <=1
|
|
if (recursiveInput.list.length <= 1) {
|
|
let result = {
|
|
recursiveInput: {
|
|
bottleneckedByComparison: false,
|
|
list: recursiveInput.list,
|
|
},
|
|
links: links,
|
|
};
|
|
return result;
|
|
}
|
|
|
|
const left = recursiveInput.list.slice(0, half); // the first half of the list
|
|
const right = recursiveInput.list.slice(half, recursiveInput.list.length); // Note that splice is destructive, and that slice instead creates a new array.
|
|
let orderedFirstHalfAnswer = mergeSortInner({
|
|
recursiveInput: { list: left, bottleneckedByComparison: false },
|
|
links,
|
|
});
|
|
let orderedSecondHalfAnswer = mergeSortInner({
|
|
recursiveInput: { list: right, bottleneckedByComparison: false },
|
|
links,
|
|
});
|
|
if (
|
|
orderedFirstHalfAnswer.recursiveInput.bottleneckedByComparison == false &&
|
|
orderedSecondHalfAnswer.recursiveInput.bottleneckedByComparison == false
|
|
) {
|
|
let mergeStepAnswer = merge(
|
|
links,
|
|
orderedFirstHalfAnswer.recursiveInput.list,
|
|
orderedSecondHalfAnswer.recursiveInput.list
|
|
);
|
|
if (mergeStepAnswer.finishedMerge == true) {
|
|
let result = {
|
|
recursiveInput: {
|
|
list: mergeStepAnswer.orderedList,
|
|
bottleneckedByComparison: false,
|
|
},
|
|
links,
|
|
};
|
|
return result;
|
|
} else {
|
|
let result = {
|
|
recursiveInput: {
|
|
list: recursiveInput.list,
|
|
bottleneckedByComparison: true,
|
|
uncomparedElements: mergeStepAnswer.uncomparedElements,
|
|
},
|
|
links,
|
|
};
|
|
return result;
|
|
}
|
|
} else if (
|
|
orderedFirstHalfAnswer.recursiveInput.bottleneckedByComparison == true
|
|
) {
|
|
return orderedFirstHalfAnswer;
|
|
} else {
|
|
return orderedSecondHalfAnswer;
|
|
}
|
|
}
|
|
|
|
export function mergeSort({ list, links }) {
|
|
// Try normally
|
|
let answer = mergeSortInner({
|
|
recursiveInput: { list, bottleneckedByComparison: false },
|
|
links,
|
|
});
|
|
if (answer.recursiveInput.bottleneckedByComparison == false) {
|
|
let result = {
|
|
finishedOrderingList: true,
|
|
orderedList: answer.recursiveInput.list,
|
|
};
|
|
return result;
|
|
} else {
|
|
let result = {
|
|
finishedOrderingList: false,
|
|
uncomparedElements: answer.recursiveInput.uncomparedElements,
|
|
};
|
|
return result;
|
|
}
|
|
/*
|
|
// otherwise, test all other permutations:
|
|
let permutation = list.slice();
|
|
var length = list.length;
|
|
// let result = [list.slice()];
|
|
let c = new Array(length).fill(0);
|
|
let i = 1;
|
|
let k;
|
|
let p;
|
|
let counter = 0;
|
|
|
|
while (i < length) {
|
|
counter++;
|
|
if (counter > 10) console.log(counter);
|
|
if (c[i] < i) {
|
|
k = i % 2 && c[i];
|
|
p = permutation[i];
|
|
permutation[i] = permutation[k];
|
|
permutation[k] = p;
|
|
// ++c[i];
|
|
c[i] = c[i] + 1;
|
|
i = 1;
|
|
let answer = mergeSortInner({ list: permutation, links });
|
|
if (answer != errorMsg) {
|
|
console.log(answer);
|
|
return answer;
|
|
}
|
|
// result.push(permutation.slice());
|
|
} else {
|
|
c[i] = 0;
|
|
i = i + 1;
|
|
// ++i;
|
|
}
|
|
}
|
|
console.log("Error");
|
|
return "Error: The original list was wrongly ordered, and trying permutations didn't work";
|
|
*/
|
|
}
|