Lets say we have the 10 integers from 1 to 10.
We also have some players who are each given a different random number from this set.
Now players start to say information about his or her number by saying: my number is in a subset of initial 1 to 10 set. For example my number is 8,9 or 10.
We want to make assumptions about number of players who didn’t say anything yet (of-course its same assumption about each silent player given initial information)
Lets say we have 5 players and the first 3 players said one by one:
- mine is 8, 9 or 10
- mine is 7 or 6
- mine is 7, 6, 9 or 10
Now we need to calculate what are the odds (probability) that next player has a specific number, like what are the odds that next player has a number in 7.
Its just an example of course and information can be given in any form by each player (like 1 or 10, 1 through 10 etc)
Is this some kind of well known problem or maybe someone sees a good approach?
I really want this to be performant, so bruteforcing isn’t good. I am thinking it could be directly connected to Bayes theorem but not 100% sure it can be applied here.
EXAMPLE:
Simple case 2 players and 12345 numbers. First player has 4 or 5.
Then for second player he has 25% to have 1, but only 12.5% to have 4 because there are 2 possible outcomes after first players says information about his hand.
1234 or 1235, we can see that 1 is (1/4 * 2) /2 =1/4 and 4 is (1/4 * 1) / 2= 1/8
This is what I call a brute force solution, compute all possible combinations and derive number probability by analyzing each of them.
UPDATE
Solution suggested by Mr.Wizard works.
Here is the code if your curious how it looks:
class Program
{
static void Main()
{
int length = 5;
double[][] matrix = new double[length][];
for (int i = 0; i < length; i++) {
matrix[i] = new double[length];
}
for (int i = 0; i < length; i++) {
for (int j = 0; j < length; j++) {
matrix[i][j] = 1;
}
}
matrix[0] = new double[] { 0, 0, 0, 1, 1 };
matrix[1] = new double[] { 0, 0, 1, 1, 0 };
matrix[2] = new double[] { 0, 0, 0, 0, 1 };
DumpMatrix(matrix);
while(true)
{
NormalizeColumns(matrix);
DumpMatrix(matrix);
NormalizeRows(matrix);
DumpMatrix(matrix);
Console.ReadLine();
}
}
private static void NormalizeRows(double[][] matrix)
{
for (int i = 0; i < matrix.Length; i++)
{
double sum = matrix[i].Sum();
for (int j = 0; j < matrix.Length; j++) {
matrix[i][j] = matrix[i][j] / sum;
}
}
}
private static void NormalizeColumns(double[][] matrix)
{
for (int j = 0; j < matrix.Length; j++)
{
double columnSum = 0;
for (int i = 0; i < matrix.Length; i++)
{
columnSum += matrix[i][j];
}
for (int i = 0; i < matrix.Length; i++) {
matrix[i][j] = matrix[i][j] / columnSum;
}
}
}
private static void DumpMatrix(double[][] matrix)
{
for (int i = 0; i < matrix.Length; i++) {
for (int j = 0; j < matrix.Length; j++) {
Console.Write(matrix[i][j].ToString("0.#####").PadRight(8));
}
Console.WriteLine();
}
Console.WriteLine();
}
}
Although from this example its pretty clear that its approaching final results not very fast.
Here player 3 has exactly 5, players one and two can have 4 or 5 and 3 or 4 respectively, which means that player one has 4 cause player 3 got 5 and player 2 has 3 cause player 2 got 4. But we approach 1 value for players 1 and 2 in matching column after many many iterations.
I may be well off the mark here, but I think that a process of repetitive normalization of each row and column will converge on the correct values.
If you start with a n*n matrix with zeros representing what cannot be, and ones representing what can, for your example:
Meaning, that row #1, representing player #1, can be only either 4 or 5, and nothing else is known. Then, if we normalize each row such that it sums to 1, we get:
And then, for each column:
Repeat this process 15 times, and we get:
If the original parameters are not impossible, then each row and column in the final matrix should sum to ~= 1.
I offer no proof that this is correct, but if you already have a working brute force implementation it should be easy to check for correlation of results.