Matching people with similar rating? - javascript

Suppose you have a collection of people with a sample size of 10,000. Each person in the collection has a rating score in the form of a winning percentage: 0.00 < x < 1.00.
Currently my system randomly picks two people and matches them together. I would like to improve matchmaking by pairing up people who have a high winning percentage with others that have a high winning percentage.
Have you ever played World of Warcraft arenas? Typically if you are in 2000 bracket you are matched with teams who are in 2000 bracket. If you are in 1500 bracket, you are matched with people who have similar ranking.
What is the the easiest way to implement such matchmaking system? While implementation doesn't really matter, even a pseudo-code would help, but I would greatly appreciate if you can guide me in the right direction using JavaScript, Backbone, and Underscore as a toolbelt.

Place everybody in a balanced binary tree (if you'll be frequently adding and removing people) or in a sorted array (if the data set is more or less static), using their winning percentage as the sort key. To match somebody, locate them in the tree or array, then match them with somebody within, say, +/- 10 rankings using a random number generator (e.g., if you're using an array and the person is in the ith index, then match them with the person at the i + rand(10) + 1 index).
I'm assuming that somebody's winning percentage will only change by small increments, which means that updating the tree or array will usually be a constant time operation since you'll just be swapping adjacent elements.

Related

Map a given amount of points in space to form a number

I wonder if there's an easy way to map a given amount of points in space to form a number?
For example: if I have 14 points, and I want to form the number 4
I'd get something like this
though if I had only 6 dots and still wanted to create the same number I'd get something like this:
You might have better luck getting a good answer from an art & design community. If I had to do this, I'd start by defining the minimum number of points for each digit along with the configuration of those points. Then, I'd allocate extra points to break up larger gaps into smaller ones roughly equally around the digit.
E.g., your 6-dot 4 might be the base case (so reject an input smaller than 6), then each segment (between pairs of adjacent points in the base case) gets 1/5 of the extra points spread evenly between the pair, with some ordering of the segments to cover cases when the additional points don't divide equally by 5.

Detect if JavaScript array of random numbers are all multiples of each other?

I'm generating an array of 5 random numbers. Once generated, I want to ensure that they're all not multiples of each other (super strange edge case). If they are, I want to regenerate them. So I don't want to see [2,4,6,8,10] or [4,8,12,16,20].
How would I detect that?
The most straightforward way is to sort them and then check to see if the lowest value is a divisor of all of them. If it is, check to see if the next number is a divisor of the ones that come after. etc. etc.
Easiest way is to create an array of 100 prime numbers then generate 5 unique numbers under 100 and use this to get the value at the numbered index of the prime numbers array. You will then guarantee the none of the numbers are multiples of each other.

How to remove duplicate part-elements from elements without being biased towards elements that occur later

I know that is a horrible title. I am not trained in CS so I haven't taken an algorithms course to know what this might be.
Let me explain:
I have an array that holds sets of 6 numbers:
var theList = [{[1,2,3,4,5,6],[1,2,3,4,5,7],[1,2,3,4,6,7],[1,3,4,5,6,7]}];
This array can be large. I then go through each item in the array and count the occurrences of the different groups of three in there. ie 1 2 3 appears 3 times, 2 3 4 appears 3 times, etc. I hold this information in another array with the count it appears as index 3 :
var countList = [{[1,2,3,3],[2,3,4,3]}]
The next thing I do is I go through each group of six (from theList) and I check my countList for the number of occurrences each of the groups of three. If they are all greater than 1, I delete this group of six, decrease the count in my countList and go on to the next number.
This seems to work, however the numbers that remain contain numerous amounts of groups of three from the higher end of the numbers. For instance if the numbers are from 1-10, when the calculations are complete there are few occurrences of the lower groups of three ([1,2,3],[1,2,4][1,2,5]), etc but there are many occurrences of the higher groups of three ([6,7,8],[7,8,9][8,9,10]) so what I end up is a bunch of groups of six that start with low numbers that seem to be taken out from the duplicate search, but they all end in the same few high numbers.
My take on it is that because the countList is sorted and the groups of six list (theList) is sorted, it "sees" those lower groups of threes more often and removes the sixes with them, but by the time it gets to the higher numbers the lower ones have all been removed so they "have" to be there.
Is there an algorithm I can look into for this?
I apologize if this is confusing, and thanks for the help.
As you state, since theList is sorted, you have a bias of removing lower runs than higher runs. If you would like symmetry, then one way would be to randomly shuffle theList before starting the removal phase.
Randomly shuffling a (Javascript) array is a well-known problem. See this community Wiki question, for ready-to-use answers.

algorithm to generate short unique human readable id from first and last name

looking for an algorithm that when given a First and a last name, an id is generated such that it consists of purely alphanumeric characters. Also, I would want this to be as short as possible whilst maintaining uniqueness. I was hoping for around 10-12 characters - something that a human could enter.
I have read about suggestions of computing a hash, then simply taking the first n bytes and calling modulus with 36 (the idea is that you have a mapping from 0-35 to the letters a-z 0-9).
Also heard suggestions of maybe truncating and using a higher base to pack more bits into the id.
I guess I could append some encoding of the generation time to the produced id to make it unique but again I need a way for this to be short.
What's your opinion? Are there specific hashing algorithms/truncating methods I should go for? I'll be implementing it in javascript as part of a static html page used as a local webapp.
I am just worried as crypto is hard and I would welcome advice from anyone who thinks they know what they are doing with it.
If it helps the number of ids I expect to make is small - around 4 digits.
One technique would be to just use a combination of the first name and last name, similar to how large companies create email aliases. If you only are creating a few thousand, it wouldn't be hard to work around collisions. These are probably the most human friendly type of id to deal with. For example, Bill Smith would be billsm or something similar.
If you don't want your ids to be easily guessable (though if guessing an id breaks your security model you should probably look into that) then you can go with something like the following (untested javascript pseudocode):
var sequence = 1,
shardId = 1,
epoch = 1357027200000;
function nextId() {
sequence = sequence + 1;
now = Date.now() - epoch;
seqId = sequence % 1023
nextId = now << 15 | shardId << 10 | seqId;
return (nextId).toString(36);
}

Concatenate nested array to vector?

Given I have an array like this:
array = [Array[8], Array[8], Array[8], ...]
# array.length is 81; each octet represents a point on a 9x9 grid
where each nested array contains 8 numeric elements ranging from -2 to 2, how would I apply the following step to get a vector in Javascript?
Step 5. The signature of an image is simply the concatenation of the
8-element arrays corresponding to the grid points, ordered
left-to-right, top-to-bottom. Our signatures are thus vectors of
length 648. We store them in 648-byte arrays, but because some of the
entries for the first and last rows and columns are known to be zeros
and because each byte is used to hold only 5 values, signatures could
be represented by as few as ⌈544 log2 5⌉ = 1264
bits.
(Towards the end, those are supposed to be ceiling notations; best I could do given SO's lack of Latex formatting)
I have the array ready to go and ordered properly, but my knowledge of matricies and vectors is a little rusty, so I'm not sure how to tackle this next step. I'd appreciate any clarifications!
Background: I'm trying to create a JS implementation of an image processing algorithm published by the Xerox Palo Alto Research Center for a side-project I'm currently working on.
Conceptually you could convert this to a single 1264 bit number using the following algorithm:
Initialize an accumulator variable to zero
Iterate over all elements, but skipt those which you know to be zero
For the other elements, add 2 to obtain values in the range [0,1,2,3,4]
For each such value, multiply the accumulator by 5 then add the corresponding value
When you have processed all elements, the accumulator will encode your arrays
To reverse that encoding, youd do this:
Read the encoded value into the accumulator
Iterate over all elements, in reverse order, but skipt those which you know to be zero
For each element, you obtain the corresponding value as the accumulator modulo 5
Subtract 2 from that value
Divide the accumulator by 5 using a truncating division
The problem with all of this is the fact that JS doesn't provide 1264 bit numbers out of the box. You might try one of the libraries suggested in How to deal with big numbers in javascript.
But unless you absolutely requre an extremely small representation, I'd suggest an alternative approach: you can encode up to 13 such values in a 32 bit signed integer, since 513=1,220,703,125 < 2,147,483,648=231. So after encoding 13 values I'd write out the result using such a number, then reset the accumulator to zero. This way you'll need ⌈544/13⌉∙32=1376 bits, which is not that much worse in terms of space requirements, but will be a lot faster to implement.
Instead of iterating once in forward and once in reverse direction, it might be easier to not multiply the accumulator by 5, but instead multiply the value you add to that by a suitable power of 5. In other words, you maintain a factor which you initialize to 1, and multiply by 5 every time you add a value. So in this case, first data values will have less significant positions than later data values, both for encoding and decoding, which means you can use the same iteration order for both.
See the ideone link mentioned in my comment below for an example of this latter approach. It encodes the full 9*9*8 values in 50 integers, each of them using no more than 31 bits. It then decodes the original matrix from that encoded form, to show that all the information is still present. The example does not use any fixed zeros, in your case ⌈544/13⌉=42 integers should be enough.

Categories