Since the puzzle is basically related to finding the minimal cost of analyzing all the names, we need to figure out the cost of assigning each name to the different programmers. The cost associated with each (name, programmer) pair is quite straightforward given all the weird behaviors described for each programmer :-)
Let's use matrix c[n, n] (bad feeling here because we are looking at n^2 at least here) to store the cost values where n is the number of names and m is the number of programmers. c[i, j] represents the cost for assigning name[i] to programmer j.
For i = 1 to n {
parse name[i] to get length[i], vowel[i], consonant[i];
for j = 1 to n {
c[i, j] = length[i];
if(j%2 == 0) c[i, j] += vowel[i]*1.5;
else c[i,j] += consonant[i];
//Need to find the greatest common divider
gcd = GCD(length[i], j);
//find the prime factors of the gcd
k = factor(gcd);
c[i,j] += k*2;
}
}
Now that we have the cost matrix, the problem basically becomes how to pick n values from this matrix so that the sum of these n values is minimized. In addition, these n values cannot share the same row or column numbers with each other. The solution to this part might be obvious to anyone with CS background, but it took me some time to associate this problem with an interesting problem (mincost maxflow) in graph theory: If we view the 26 names as 26 nodes on the left side and the 26 programmers as 26 nodes on the right side, then each left node has a full mesh connection to the 26 right nodes forming a bipartite graph; we can view each connection from left to right as having capacity 1, but the cost is equal to c[i, j]. In addition, if we connect a virtual source node to the 26 left nodes and a virtual sink node to the 26 right nodes, assuming the virtual connection each have capacity 1 and the same cost (e.g. 1), then the problem now becomes how to find the max flow from the source node to the sink node with lowest cost. The max flow in this case is always 26, but the minimal cost and mapping structure is what we want to find here.
More details will come ...
Other stuff related to the above solution:
1. Find the GCD of two numbers (Facebook programmers really like GCD as it is used also in the Korn shell puzzle):
GCD(i, j)
{
if (j==0) return i;
return gcd(j, i%j);
}
2. Find the prime factorization of a number. This is supposed to be a difficult problem as many of the crypto algorithms rely on the fact that it is hard to factor numbers. But luckily we are dealing with small numbers here (first of all, only 26 characters used; second of all, hope any reasonal people will not give their child a long name that takes hours or more to write :-)), so the follow simple algorithm should do:
factor(n)
{
k = 0; factor = 2;
while(n > factor) {
if (n%factor == 0) {
n = n/factor;
k++;
} else { factor++;
}
}
return k;
}
The return value k is the number of primes that n can be factored into.