I have an array of teams, I am trying to split that array into multiple arrays with having minimum players in each array. I mean, form the array into multiple teams from array. I forgot what this feature is called, but let me tell you with an explanation:
minimum players: 3
team array: [4, 6, 5, 8]
This array will form like this:
[
[4, 6, 5],
[4, 6, 8],
[4, 5, 8],
[6, 5, 8],
[4, 6, 5, 8]
]
So, I have tried doing this problem, but I got stuck that what to do and how to do.
function teams(minPlayers, arr) {
for (let i = 0; i < arr.length; i ) {
const subArray = []
let startMax = minPlayers - 2
let end = minPlayers
for (let j = 0; j < arr.length; j ) {
if (j < startMax) {
subArray[i] = arr[i]
}
}
}
}
console.log(teams(3, [4, 6, 5, 10]))
It will be a pleasure if you help me.
CodePudding user response:
Here is a generator that generates the combinations through recursion. Array.from
will consume the iterator:
function teams(minPlayers, arr) {
// Execute a generator, and pass it to Array.from to turn its
// yielded values into an array and return it
return Array.from(function* iter(minPlayers, start) {
// When there are as many remaining elements (from start)
// as we need players, then there are no other options
// than selecting all those values, so yield that slice of
// the array and return (base case)
if (arr.length - minPlayers == start) return yield arr.slice(start);
// Produce the cases where the element at start is not selected.
// Use recursion for this, by reducing the slice that is still available
yield* iter(minPlayers, start 1);
// Produce the cases where the element at start is selected.
// Use recursion to get the combinations after that, and
// prefix the start element to each of those
for (let combi of iter((minPlayers || 1) - 1, start 1)) {
yield [arr[start], ...combi];
}
}(minPlayers, 0)); // Immediately execute the generator function
}
console.log(teams(3, [4, 6, 5, 10]));
So the idea of the generator is to either take the current value or not (current is arr[start]
). In either case, defer the other selections to recursion. The recursive call will get an increased start
value so there are fewer elements to choose from.
CodePudding user response:
This is not exactly permutation quite the opposite since we don't care for order, but we do care for picking n
different items.
The recursive function picks
works by picking an item
(length times) then running picks
on the rest - concatenating the results. A care is given not to pick numbers that are "left" to the position of our current item
position since we already counted them.
// this loops over minPlayers to maxPlayers (length)
function teams(minPlayers, arr) {
var result = [];
for (var i = minPlayers; i <= arr.length; i ) {
result = result.concat(picks(i, arr))
}
return result;
}
// picks all possible n items from arr (hopefully)
function picks(n, arr) {
// will hold all possible series (pick of n items from array)
var result = [];
if (n == 1) {
// base case return n arrays of 1 item
for (var i = 0; i < arr.length; i ) {
result.push([arr[i]])
}
return result;
}
// else we will loop over each of items
for (var i = 0; i < arr.length; i ) {
// make a copy since we are going to remove items from it
var copy = [...arr];
// pick an item, the first one of our series
var item = copy.splice(i, 1);
// ignore those before it
for (j = 0; j < i; j ) {
// remove an item from beginning of array
copy.shift();
}
// recursion! get picks of the rest n-1 items
var others = picks(n - 1, copy);
// combine each pf those picks with our item
others.forEach(function(other) {
// push to result the series which is [item, ...rest]
result.push(item.concat(other))
})
}
// return array of arrays
return result;
}
console.log(teams(3, [4, 6, 5, 10]))
.as-console-wrapper {
max-height: 100% !important;
}
Last function can be refactored a little since base case looks similar to the other steps and no need to mutate the array. Here's the shorter version:
// loop for each possible minPlayers and above
function teams(minPlayers, arr) {
var result = [];
for (var i = minPlayers; i <= arr.length; i ) {
result = result.concat(picks(i, arr))
}
return result;
}
// recursive function to pick all possible n items from arr
function picks(n, arr) {
var result = [];
for (var i = 0; i < arr.length; i ) {
// foreach item
var item = arr[i];
if (n == 1) {
// if we need pick 1, then pick item
result.push([item])
} else {
// pick n-1 possible except our item (and those before it)
var others = picks(n - 1, arr.slice(i 1));
// combine with our item n times
others.forEach(function(other) {
result.push([item, ...other])
})
}
}
return result;
}
console.log(teams(3, [4, 6, 5, 10]))
.as-console-wrapper {
max-height: 100% !important;
}