Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/382.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 找到总长度为10的数组的随机组合,并可拆分为两组,每组5个_Javascript_Combinations - Fatal编程技术网

Javascript 找到总长度为10的数组的随机组合,并可拆分为两组,每组5个

Javascript 找到总长度为10的数组的随机组合,并可拆分为两组,每组5个,javascript,combinations,Javascript,Combinations,假设我有一个带有数组的数组,例如: const array = [ ['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h', 'i', 'j'], ['k'], ['l'], ['m'], ['n', 'o', 'p'], ['q', 'r', 's'], ['t', 'u', 'v'], ['x'] ]; 我想随机选择符合以下规则的任意组合: 所有选定组合的总长度必须始终为10。

假设我有一个带有数组的数组,例如:

const array = [
    ['a', 'b', 'c'],
    ['d', 'e'],
    ['f', 'g', 'h', 'i', 'j'],
    ['k'],
    ['l'],
    ['m'],
    ['n', 'o', 'p'],
    ['q', 'r', 's'],
    ['t', 'u', 'v'],
    ['x']
];
我想随机选择符合以下规则的任意组合:

  • 所有选定组合的总长度必须始终为10。可能的结果是
    数组的前3项
  • 所选组合必须能够分为两组,每组5个。同样,前3个项目将遵守该条件:
    ['a',b',c']
    +
    ['d',e']
    长度等于
    5
    ,同时
    ['f',g',h',i',j']
    的长度等于
    5
    。这是两组
    5
    。另一方面,
    数组的最后4个元素
    将无法满足此条件,即使它们尊重第一个元素(总长度=10)
这可能有助于了解其目的:我有一个小型多人游戏。比赛需要2支5人的球队。玩家可以和一个朋友进入游戏,在同一个团队中玩(甚至5个朋友,瞬间填满整个团队)

想法是:玩家会按“开始”。然后我的函数会将它们放入一个数组中,就像上面的数组一样。每次推送发生时,玩家/团队功能(我请求您的帮助)都会运行。如果找到匹配项,游戏将开始

我有一种感觉,这最好用某种递归函数来实现,但我的脑袋很难弄清楚


几个小时后,我想出了一个解决办法。通过了我所有的测试

//const { shuffle, flatten } = require('lodash');

const pool = [
    ['a', 'b', 'c'],
    ['d', 'e'],
    ['f', 'g', 'h', 'i', 'j'],
    ['k'],
    ['l'],
    ['m'],
    ['n', 'o', 'p'],
    ['q', 'r', 's'],
    ['t', 'u', 'v'],
    ['x']
];

function getMaxPickSize ( draw ) {
    let x = 5;
    let y = 5;

    draw.forEach( pick => {

        if ( x - pick.length >= 0 ) {
            x -= pick.length;

        } else if ( y - pick.length >= 0 ) {
            y -= pick.length;
        }

    });

    return Math.max(x,y);
}


function doDraw( pool ) {
    //no need to move further if there arent even 10 players
    if ( _.flatten(pool).length < 10 ) {
        return false;
    }

    // keep register of all draws and pools, and items. if we 
    // figure out an attempt doesnt work, we can go back anytime
    // and skip picks that dont work
    let prevs = [
        // array of objects that will look like this.
        // {   
        //     pool: [],
        //     draw: [],
        //     skip: []
        // }
        // ...
    ];

    //let's try. First step, shuffle the pool;
    pool = _.shuffle(pool);

    function doIt( curr_pool, curr_draw = [], skip_items_w_length ) {

        let new_pool = [...curr_pool];
        let new_draw = [...curr_draw];
        let pick;

        if ( skip_items_w_length == undefined ) {
            //in first loop it starts here
            //if we happen to have luck and fill the draw in
            //one go, the else statement below will never execute
            pick = new_pool.shift();

        } else {

            let to_skip = prevs[prevs.length - 1].skip;
            to_skip.push(skip_items_w_length);

            pick = _.find(new_pool, item => !to_skip.includes(item.length) );

            if ( pick ) {
                new_pool.splice(new_pool.indexOf(pick), 1);

            } else {
                if ( !prevs.length ) {
                    return false;
                }

                let prev = prevs.pop();
                let prev_pool = prev.pool;
                let prev_draw = prev.draw;
                let last_item_in_prev_draw = prev_draw.pop();

                return doIt(prev_pool, prev_draw, last_item_in_prev_draw.length );
            } 
        }

        new_draw = [...curr_draw, pick];

        //if draw is complete, return it
        if ( _.flatten(new_draw).length === 10 ) {
            return new_draw;
        }


        //else draw process continues
        //find items in pool that can still fit into draw
        const max_pick_size = getMaxPickSize(new_draw);
        new_pool = new_pool.filter(item => item.length <= max_pick_size);

        //if items dont contain enough players to fill remaining spots,
        //repeat this exact step, ignoring items without pick's length
        //as none of the remaining picks can follow. if we discover in
        // later repeats that no pick allows other picks to follow
        // we'll go back 1 step, using previous pool and draw, and
        // ignoring all picks with the associated picks length
        if ( _.flatten(new_pool).length < 10 - _.flatten(new_draw).length ) {
            return doIt(curr_pool, curr_draw, pick.length);
        }


        prevs.push({
            pool: curr_pool,
            draw: curr_draw,
            skip: []
        });

        return doIt(new_pool, new_draw);
    }


    return doIt(pool);

}

const draw = doDraw( pool );
//const{shuffle,flant}=require('lodash');
常量池=[
[a',b',c'],
['d','e'],
[f',g',h',i',j'],
[k'],
['l'],
['m'],
[n',o',p'],
[q',r',s'],
[t',u',v'],
['x']
];
函数getMaxPickSize(绘制){
设x=5;
设y=5;
draw.forEach(pick=>{
如果(x-pick.length>=0){
x-=拾取长度;
}如果(y-pick.length>=0),则为else{
y-=拾取长度;
}
});
返回Math.max(x,y);
}
函数doDraw(池){
//如果连10名球员都没有,就不需要再往前走了
如果(u.展平(池)。长度<10){
返回false;
}
//保留所有提款、池和项目的登记。如果我们
//如果你想办法不奏效,我们随时都可以回去
//跳过那些不起作用的选择
设prevs=[
//看起来像这样的对象数组。
// {   
//池:[],
//提款:[],
//跳过:[]
// }
// ...
];
//让我们试试。第一步,洗牌池;
pool=\洗牌(pool);
函数doIt(当前池,当前绘图=[],跳过项目长度){
让new_pool=[…curr_pool];
让新绘图=[…当前绘图];
让我们挑选;
如果(跳过项目长度==未定义){
//在第一个循环中,它从这里开始
//如果我们运气好的话,就可以抽签了
//一次过,下面的else语句将永远不会执行
pick=new_pool.shift();
}否则{
let to_skip=prevs[prevs.length-1]。跳过;
要跳过。推送(跳过项目长度);
pick=u.find(新的_池,项=>!to_skip.includes(项.长度));
如果(选择){
新池拼接(新池索引(pick),1);
}否则{
如果(!上一个长度){
返回false;
}
设prev=prevs.pop();
让prev_pool=prev.pool;
让prev_draw=prev.draw;
让_prev_draw中的最后一个_项_=prev_draw.pop();
返回doIt(上一个池、上一个绘图、上一个绘图中的最后一个项目长度);
} 
}
新绘图=[…当前绘图,拾取];
//如果抽签完成,请将其返回
如果(u.flant(新绘制).length==10){
返回新的_-draw;
}
//否则将继续绘制过程
//在池中查找仍可放入绘图的项目
常量最大拾取大小=getMaxPickSize(新绘制);

new_pool=new_pool.filter(item=>item.length洗牌数组,然后取出唯一的组,直到达到五个:

const数组=[
[a',b',c'],
['d','e'],
[f',g',h',i',j'],
[k'],
['l'],
['m'],
[n',o',p'],
[q',r',s'],
[t',u',v'],
['x']
];
函数洗牌(arr){/*这里的洗牌算法*/}
洗牌(阵法);
//提取具有精确“count”元素的数组,排除“exclude”中的所有元素,并从数组中的“start”开始
//如果未找到组合,则返回undefined
函数抽头(数组、计数、开始=0、排除=[]){
//基本情况:未精确达到计数,请在此处中止
如果(计数<0)返回;
//基本情况:发现组合,上升
if(count==0)返回[];
//检查数组以找到匹配的组合
for(设i=start;iconsole.log(“游戏可以开始”);
我想出的解决方案可能不是您想要的。无论如何,我认为它可能会帮助您。它会找到所有可能的组合,如果您只需要一个,您可以随机选择。我还使用