const intersect = (a, b) => {
return new Set([...a].filter(x => b.has(x)));
}
const setsEqual = (a, b) => [...a].sort().toString() == [...b].sort().toString();
const prefs = {
Bob: { pref: 1 },
Sue: { pref: 1 },
Sal: { pref: 1 },
Jim: { pref: 2 },
Jon: { pref: 2 },
Lyn: { pref: 2 },
Ian: { pref: 3 },
Sam: { pref: 3 }
};
const names = Object.keys(prefs);
const randomName = () => names[~~(Math.random() * names.length)];
const randomList = () => new Array(5).fill().map((_, orig) => {
const name = randomName();
return { name, orig };
}).sort((a, b) => prefs[a.name].pref > prefs[b.name].pref ? 1 : -1);
const people = {};
for (let i = 0; i < 100; i++) {
const list = randomList();
list.forEach(({ name }) => !people[name] && (people[name] = {
superiors: new Set(), inferiors: new Set()
}));
list.forEach(({ name, orig }, yourPos) => {
const superiors = people[name].superiors;
const inferiors = people[name].inferiors;
list.forEach((person, theirPos) => {
if (person.name == name) return;
if (theirPos < yourPos && person.orig > orig) {
superiors.add(person.name);
}
if (theirPos > yourPos && person.orig < orig) {
inferiors.add(person.name);
}
});
});
}
Object.entries(people).forEach(([name, { superiors, inferiors }]) => {
const intersection = intersect(superiors, inferiors);
for (const elem of intersection) {
superiors.delete(elem);
inferiors.delete(elem);
}
});
Object.entries(people).forEach(([yourName, person]) => {
Object.entries(people).forEach(([theirName, other]) => {
const yourInferiors = person.inferiors;
const yourSuperiors = person.superiors;
const theirInferiors = other.inferiors;
const theirSuperiors = other.superiors;
if (setsEqual(yourInferiors, theirInferiors) && setsEqual(yourSuperiors, theirSuperiors)) {
person.equals = person.equals || new Set();
other.equals = other.equals || new Set();
person.equals.add(theirName);
other.equals.add(yourName);
person.equals.add(yourName);
other.equals.add(theirName);
}
});
});
const rankedPeople = Object.entries(people).sort(([, a], [, b]) => {
return a.superiors.size > b.superiors.size ? 1 : -1;
}).map(([name, { equals }]) => {
return { name, equals: [...equals].sort().toString() };
});
const groups = [...new Set(rankedPeople.map(({ equals }) => equals))]
.map((group, pref) => ({ pref: pref + 1, group: group.split(',') }));
const deduction = {};
groups.forEach(({ pref, group }) => {
group.forEach(name => {
deduction[name] = pref;
});
});
console.log(deduction);