Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

第六天:分组 #8

Open
sofish opened this issue Apr 21, 2016 · 11 comments
Open

第六天:分组 #8

sofish opened this issue Apr 21, 2016 · 11 comments
Milestone

Comments

@sofish
Copy link
Owner

sofish commented Apr 21, 2016

几乎每次面试都问一个题:一群人出去玩,写一个程序随机分组可以如何分。最后简化成 10 个人出去玩,如何将人随机分配到 4 个组里,并保证每个组的人比较均匀。

var arr = [1,2,3,4,5,6,7,8,9,0];
var group = [[],[],[],[]];

(function split(arr, group) {
  // you code here


  console.log(group);
})(arr, group);

不想直接给答案,有订阅的大家思考一下,有兴趣的可以评论发自己的答案。也是留给老婆的一道题。考点包括随机、数组操作、基本的流程控制。

补:昨天又忘记了 ( 👎 )

@sofish sofish added this to the Daily Post milestone Apr 21, 2016
@csvwolf
Copy link

csvwolf commented Apr 21, 2016

我的思路是,首先先随机排序,之后保证每组人数相对较均匀即可,请小鱼老师多多指教QuQ

var arr = [1,2,3,4,5,6,7,8,9,0];
var group = [[],[],[],[]];

(function split(arr, group) {
  // you code here
  var groupSize = group.length,
      totalSize = arr.length;

  // 随机排序
  arr.sort(function() {
    return Math.random() * 2 - 1;
  });

  // 接下来保证每组数量比较平均即可
  group.forEach(function(elem, index) {
    var size = Math.floor(totalSize / groupSize);
    for (var i = 0; i < size; i++) {
      elem.push(arr.pop());
    }

    totalSize -= size;
    groupSize--;
  });

  console.log(group);
})(arr, group);

@nimoc
Copy link

nimoc commented Apr 22, 2016

var arr = [1,2,3,4,5,6,7,8,9,0]
var group = [[],[],[],[]]

function shuffle (arr) {
    return arr.sort(function () {
       return Math.round(Math.random())
    })
}

;(function split(arr, group) {
    // 打乱数组
    var randomArr = shuffle(arr)

    // 向下舍入的平均整数
    var floorAverage = Math.floor(randomArr.length/group.length)

    // 先按平均整数分配蛋糕
    var output = group.map(function () {
        item = randomArr.splice(0,floorAverage)
        return item
    })

    // 如果还有蛋糕遍历一遍分配给所有人(没分到的算倒霉)
    if (randomArr.length) {
        output = output.map(function (item) {
           item = item.concat(randomArr.splice(0,1))
           return item
        })
    }
    // 再次洗牌避免永远是前几个蛋糕多,后几个蛋糕少
    output = shuffle(output)
    console.log(JSON.stringify(output))
    // [[3,5,8],[7,1],[4,2,9],[6,0]]
})(arr, group)

@sofish
Copy link
Owner Author

sofish commented Apr 22, 2016

分享一个我的思路:

'use strict'

var arr = [1,2,3,4,5,6,7,8,9,0];
var group = [[],[],[],[]];

(function split(arr, group) {

  var size = group.length; // 分多少组
  var length = arr.length; // 人数总长度

  // 每次随机叫一个人,跳进一个组里,并从原数组里踢掉
  while(arr.length) {
    for(let i = 0; i < length; i++){ 
      let index = Math.random() * arr.length | 0;  // 随机
      group[i % size].push(arr[index]);            // 入组
      arr.splice(index, 1);                        // 踢掉
    }
  }

  console.log(group);
})(arr, group);

补充:分享一个 Fisher-Yates 算法 https://bost.ocks.org/mike/shuffle/

@rccoder
Copy link

rccoder commented Apr 22, 2016

@sofish

鱼大大,假如这四个组是有区别的,你上面的这种写法貌似还是存在一些问题

每次入组的时候 都是 依次从 0/1/2 组开始入,这样最后永远是前面的几个组人数比后面几个组的人数多一个


不过感觉大大的代码好有感觉,好精干......

@sofish
Copy link
Owner Author

sofish commented Apr 22, 2016

@rccoder 嗯,如果需要有顺序排列的话,后面再重新「洗牌」就可以了:

group.sort(() => Math.random() * 2 - 1)

@rccoder
Copy link

rccoder commented Apr 22, 2016

@sofish 👍

@jununx
Copy link

jununx commented Apr 22, 2016

@sofish

鱼大大的代码,短小精干啊。

@jununx
Copy link

jununx commented Apr 22, 2016

var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0];
var group = [[], [], [], [] ]; 
;(function split(arr, group) {
    // 借用了楼上nimojs的打乱数组
    function shuffle(arr) {
        return arr.sort(function() {
            return Math.round(Math.random())
        })
    }

    arr = shuffle(arr);

    // 找到要添加的组下标
    function filterGroupIndex() {
        var res = group.map(function(v) {
            return v.length;
        });
        return res.indexOf(Math.min.apply(null, res));
    }

    // 分组
    arr.forEach(function(v) {
        group[filterGroupIndex()].push(v);
    });

    console.log(JSON.stringify(shuffle(group)));
})(arr, group);

@lljxx1
Copy link

lljxx1 commented Apr 22, 2016

'use strict'

var arr = [1,2,3,4,5,6,7,8,9,0];
var group = [[],[],[],[]];
(function split(arr, group) {

    // you code here
    var personSize = arr.length;
    var groupSize = group.length;
    var average = Math.floor(personSize / groupSize);

    function getPerson(){
        return arr.shift();
    }

    function isLastPerson(){
        return arr.length == 1;
    }

    function getGroup(index){
        return group[index]
    }

    function getRandomGroup(){
        var index = Math.floor(Math.random() * groupSize + 1)-1;
        var groupL = group[index].length;

        if(groupL < average || isLastPerson()){
            return index;
        }else{
            return getRandomGroup();
        }
    }

    function addToGroup(per){
        var index = getRandomGroup()
        group[index].push(per);
    }


    (function main(){
        var per = getPerson();
        if(!per) return;

        addToGroup(per);
        main();
    })();

    console.log(group);
})(arr, group);

@xiaoqiang730730
Copy link

码个

(function(arr, group) {
    var arr = [1,2,3,4,5,6,7,8,9,0];
    var group = [[],[],[],[]];

    var random = function(arr) { // 打乱函数
        return arr.sort(function() {
            return Math.round(Math.random()*2) - 1;
        });
    }

    var getRandom = function(arr) {// 分配
        arr = random(arr);
        return arr.splice(0, 1);
    };

    var len = Math.round(arr.length/group.length); // 分配轮数
    for (var i = 0; i < len; i++) {
        group.forEach(function(ele, index) { // 每轮依次分配
            if(!arr.length) return group;
            ele.push(getRandom(arr));
        });
    }
})(arr, group);

@sofish sofish closed this as completed Apr 22, 2016
@sofish sofish reopened this Apr 22, 2016
@toplan
Copy link

toplan commented Apr 23, 2016

@sofish 👍 入组的时候哇感觉这样更简洁:

...
  group[i % size].push(arr.splice(index, 1)[0]);    
...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

8 participants