Reputation: 544
To participate in a prize draw each one gives his/her firstname.
Each letter of a firstname has a value which is its rank in the English alphabet. A and a have rank 1, B and b rank 2 and so on.
The length of the firstname is added to the sum of these ranks hence a number som.
An array of random weights is linked to the firstnames and each som is multiplied by its corresponding weight to get what they call a winning number.
Example:
names: "COLIN,AMANDBA,AMANDAB,CAROL,PauL,JOSEPH"
weights: [1, 4, 4, 5, 2, 1]
PauL -> som = length of firstname + 16 + 1 + 21 + 12 = 4 + 50 -> 54
The *weight* associated with PauL is 2 so PauL's *winning number* is 54 * 2 = 108.
Now one can sort the firstnames in decreasing order of the winning numbers. When two people have the same winning number sort them alphabetically by their firstnames.
Task: parameters: st a string of firstnames, we an array of weights, n a rank
return: the firstname of the participant whose rank is n (ranks are numbered from 1)
Now one can sort the firstnames in decreasing order of the winning numbers. When two people have the same winning number sort them alphabetically by their firstnames.
This is my solution, but it does not account for the case when the numerical value of the name is the same(I use the first value).
function charToNumber (s, i) {
return parseInt(s.charAt(i), 36) - 9;
}
function sumChars (s, weight) {
var i = s.length, r = 0;
while (--i >= 0) r += charToNumber(s, i);
return r + s.length;
}
function rank(st, we, n) {
let result, arr
const hashTable = {};
let resultsArr = [];
arr = st.split(',')
if (st.length === 0) {
return "No participants";
} else if (n > arr.length) {
return "Not enough participants";
}
arr.forEach((name, i) => {
const total = sumChars(name) * we[i];
hashTable[name] = total;
nameMap.set(name, total);
resultsArr.push(total);
});
resultsArr.sort((a, b) => a - b).reverse();
const correctSum = resultsArr[n-1];
for (const prop in hashTable) {
if (hashTable[prop] === correctSum) {
result = prop;
break;
}
}
return result;
}
//rank('Grace,Jacob,Jayden,Daniel,Lily,Samantha,Aubrey,David,Liam,Willaim,Addison,Robert,Alexander,Avery,Isabella,Mia,Noah,James,Olivai,Emily,Ella,Sophia,Natalie,Benjamin,Lyli,Madison', [2,4,1,1,3,6,6,4,4,5,4,6,3,6,6,6,6,6,5,6,5,1,4,1,5,5], 7);
// should return 'Isabella'
//rank('Emily,Benjamin,Ava,Joshua,Isabella,Michael,Matthew,Olivai,William,Willaim,David,Lyli', [3,3,3,6,6,4,6,6,3,3,6,4], 6);
// should return 'Willaim', not 'William'
Upvotes: 0
Views: 164
Reputation: 14573
You just need a multi dimensional sort, first sort names by rank and then alphabetically (ignoring case):
var names = ["COLIN","AMANDBA","AMANDAB","CAROL","PauL","JOSEPH"];
var weights = [1, 4, 4, 5, 2, 1];
function compute_score(name, weight) {
// XXX: code for computing the actual score goes her
return weight;
}
function winner(names, weights) {
var scores = {};
for (var ii=0; ii < names.length; ii++) {
scores[names[ii]] = compute_score(name, weight);
}
return names.sort(
function (a,b) {
if (scores[a] > scores[b]) return -1;
if (scores[a] < scores[b]) return +1;
if (a.toLowerCase() < b.toLowerCase()) return -1;
if (a.toLowerCase() > b.toLowerCase()) return +1;
return 0; // equal
}
)[0];
}
console.log(winner(names, weights));
CAROL
Note I don't error check (empty lists, etc), be careful.
Upvotes: 2