javascript 函数式编程(3)

某题目1:

  某公司在北京和上海各有 N 个员工,比如北京有10员工,员工编号 1 到 10,在上海有10个员工,编号 11 到 20.

  公司的所有项目,都是2个人的team,一个来自北京,一个来自上海

  每个人可能参与多个项目,但同一个team,不会参与多个项目

  年终了,CEO要开总结会,要求每个项目都要来至少 1 个代表,来总结项目。

  由于经费有限,需要写一个程序,计算出最少的人(但每个项目都要来人),至少打印出一组数据


测试样例:

1, 16
1, 13
1, 15
2, 19
3, 16
5, 15
7, 13
7, 14
8, 14

一组可能的输出结果: 2, 13, 14, 15, 16


数学模型:

  1. 每个pair在坐标轴上可以看作一个点

  2. 水平或者竖直方向能连线的点,都算在一个group内,把所有点划分成多个group

        比如下图中被划分为2个group

  3. 一个group内,横向数线的条数,纵向数线的条数,哪个条数少就取哪个方向,所有该方向线的坐标值,就是这个group的最少组合

        Group 1横向数1条线,纵向1条线,就取横向坐标 2

        Group 2横向数5条线,纵向4条线,就取纵向坐标 13, 14, 15, 16

  4. 把所有group计算出的组合汇总到一起

        得到 2, 13, 14, 15, 16


代码:

data = [  
    [1, 16],  
    [1, 13],  
    [1, 15],  
    [2, 19],  
    [3, 16],  
    [5, 15],  
    [7, 13],  
    [7, 14],  
    [8, 14]  
];  
MAX = 10;//坐标轴上限,即一个地点的最大人数  
  
/* convert arr to map: 
{ 
    1: [13, 15, 16], 
    2: [19], 
    3: [16], 
    5: [15], 
    7: [13, 14], 
    8: [14], 
    13: [1, 7], 
    14: [7, 8], 
    15: [1, 5], 
    16: [1, 3], 
    19: [2] 
}*/  
function generateMap(arr) {  
    return reduce(function(o, pair) {  
        var k = pair[0], v = pair[1];  
        if(!o[k]) o[k] = [];  
        o[k].push(v);  
        return o;  
    }, {}, arr);  
}  
map_X = generateMap(data);//根据横坐标生成map_X  
map_Y = generateMap(flip(data));//根据纵坐标生成map_Y  
  
map = apply(map_X, map_Y);//合并为map,内容如上  
  
function apply(dest, src) {  
    for(var x in src) dest[x] = src[x];  
    return dest;  
}  
  
  
//从map生成group数组, 结构和上一篇很像, 因为都是从一个点出发寻找所有路径  
function map_2_groups(map) {  
      
    function makeGroup(el) {  
        function findRoutes(route) {  
            function notVisited(el) {  
                return !member(route.path, el);  
            }  
            function continueRoute(el) {  
                return findRoutes({  
                    path: route.path.concat(el),  
                    current: el  
                });  
            }  
  
            var rest = filter(notVisited, map[route.current]);  
            if(rest.length === 0) {  
                return route.path;  
            } else {  
                return flatten(_map(continueRoute, rest));//由于上面用到了map变量,所以map函数改成_map  
            }  
        }  
  
        var r = findRoutes({  
            path: [el],  
            current: el  
        });  
        return r;  
    }  
    function isInGroups(groups, el) {  
        return member(flatten(groups), el);  
    }  
  
    var gs = [];  
  
    forObjKey(map, function(k) {  
        if(!isInGroups(gs, k)) {  
            gs.push(unique(makeGroup(parseInt(k, 10))));  
        }  
    });  
  
    return gs;  
}  
  
function forObjKey(o, fn) {  
    for(var x in o) fn(x);  
}  
  
/* groups = [ 
    [1, 16, 3, 13, 7, 14, 8, 15, 5], 
    [2, 19] 
 ] */  
groups = map_2_groups(map);//得到所有group  
  
  
function isX(x) { return x < MAX; }  
function isY(y) { return y >= MAX; }  
  
function minimalGroup(group) {  
    var xy = reduce(function(base, el) {  
        base[isX(el) ? 0 : 1].push(el);  
        return base;  
    }, [[],[]], group);  
    //取x或y方向线条数较小,并返回该方向的所有坐标值  
    return xy[0].length > xy[1].length ? xy[1] : xy[0];  
}  
minGroup = flatten(_map(minimalGroup, groups));  

  


posted @ 2011-09-24 00:33  aj3423  阅读(166)  评论(0编辑  收藏  举报