I have an array of team names which is like this:
teams = ['team1', 'team2', 'team3', 'team4']
I want to create a set of matches based on this, so at the moment, for a set of matches using the teams array you would get:
teamMatches : [
[ teams[0], teams[1] ],
[ teams[2], teams[3] ]
]
My question is, can anyone think of a way to produce this teamMatches array based upon a teams array with length n. The teams array will always be a correct number, 4,8,16 etc. I have tried using Math.pow with 2 to try to produce the brackets with no success.
Any ideas?
A procedural solution:
xs = [0,1,2,3,4,5,6,7,8,9]
result = []
n = 2 // n=3 gives a list of triples, etc
for(var i = 0; i < xs.length; i += n)
result.push(xs.slice(i, i + n))
A functional programming solution:
function zip() {
var args = [].slice.call(arguments, 0);
return args[0].map(function(_, n) {
return args.map(function(a) {return a[n] })
})
}
xs = [0,1,2,3,4,5,6,7,8,9]
result = zip(
xs.filter(function(_, n) { return n % 2 == 0 }),
xs.filter(function(_, n) { return n % 2 != 0 })
)
// [[0,1],[2,3],[4,5],[6,7],[8,9]]
Explanation: zip is a function (built-in in some programming languages, but not in Javascript) that takes N arrays and groups together elements at the same position:
zip([1,2,3], [10,20,30]) -> [ [1,10], [2,20], [3,30] ]
We split an array into even and odd parts:
[0,2,4,6...]
[1,3,5,7...]
and zip them together, getting a list of ordered pairs.
How about this
var teams = ['team1', 'team2', 'team3', 'team4'];
var teamMatches = new Array();
for(var i=0;i<teams.length; i+=2)
{
teamMatches.push([teams[i],teams[i+1]]);
}
Related
Problem
Currently, I have two arrays (but the overall amount is dynamic, not necessarily always 2) and I need a way to sum each index of each array (as in, index 0 of array 1 + index 0 of array 2, index 1 of array 1 + index 1 of array 2 and so on..) and then store the collection of sums computed into its own array.
What the Arrays Look Like
[ 0.9716351, 1.116535, 1.316175 ] -- Array 1
[ 0.937825, 1.09963, 1.358035 ] -- Array 2
What I'm Trying to Do
I'm trying to add the indexes of Array 1 and 2 together, and store the sum of each index into a new "sum" array. As in:
sum = [0.9716351 + 0.937825, 1.116535+1.09963, 1.316175+1.358035] and so on.
I've tried mapping over the array's and summing them but it's not summing the correct indexes and storing them in a new array entirely.
Any help?
Use nested forEach, so that it work for dynamic number of arrays.
const data = [
[0.9716351, 1.116535, 1.316175],
[0.937825, 1.09963, 1.358035],
];
const res = [];
data.forEach((arr) => {
arr.forEach((item, index) => {
res[index] = (res[index] ?? 0) + item;
});
});
console.log(res);
This method will work even for any number of arrays that have any length ( They can be different)!
let arrays = [
[0.9716351, 1.116535, 1.316175],
[0.937825, 1.09963, 1.358035]
]
let sum = [];
let arrLengths = [];
for (array of arrays) {
arrLengths.push(array.length)
}
let gLength = Math.max(...arrLengths)
for (let i = 0; i < gLength; i++) {
let thisSum = 0
for (let p = 0; p < arrays.length; p++) {
thisSum += arrays[p][i] || 0;
}
sum[i] = thisSum
}
console.log(sum)
Please note: the linked question, "How can I create every combination possible for the contents of two arrays?" does not solve this particular question. The persons that labeled that did not fully understand this specific permutation and request.
If you have two arrays (arr1, arr2) with n elements in each array (i.e., each array will be the same length), then the question is: What's the best method to get/determine all the possible matches where elements do not match with other elements in the same array and where order does not matter?
For example, let's say I have:
arr1 = ["A","B","C"];
arr2 = ["Z","Y","X"];
I would like to get back an array of arrays where each element of one array is paired with an element of another array. So the result would be a unique set of arrays:
matches = [
[["A","Z"],["B","Y"],["C","X"]],
[["A","Z"],["B","X"],["C","Y"]],
[["A","Y"],["B","X"],["C","Z"]],
[["A","Y"],["B","Z"],["C","X"]],
[["A","X"],["B","Z"],["C","Y"]],
[["A","X"],["B","Y"],["C","Z"]],
]
Please note, these two arrays would be the same:
[["A","Z"],["B","Y"],["C","X"]]
[["B","Y"],["C","X"],["A","Z"]]
I am trying to do this with vanilla JavaScript but am completely open to using Lodash as well. For an added bonus, since this can get out of control, speed and performance are important. But right now, I am just trying to get something that would yield a proper result set. To limit this, this function would probably not be used with more than two arrays of 50 elements each.
Here is my latest attempt (using lodash):
function getMatches(arr1, arr2){
var matches = [];
for (var arr1i = 0, arr1l = arr1.length; arr1i < arr1l; arr1i++) {
for (var arr2i = 0, arr2l = arr2.length; arr2i < arr2l; arr2i++) {
matches.push(_(arr1).zip(arr2).value());
arr2.push(arr2.shift());
}
}
return matches;
}
[[A, 1], [B, 2]]
is the same as
[[B, 2], [A, 1]]
in your case, which means that the solution depends on what you pair to the first elements of your array. You can pair n different elements as second elements to the first one, then n - 1 different elements as second elements to the second one and so on, so you have n! possibilities, which is the number of possible permutations.
So, if you change the order of the array elements but they are the same pair, they are equivalent, so you could view the first elements as a fixed ordered set of items and the second elements as the items to permutate.
Having arr1 = [a1, ..., an] and arr2 = [b1, ..., bn] we can avoid changing the order of a1. So, you permutate the inner elements and treat the outer elements' order as invariant, like:
const permutations = function*(elements) {
if (elements.length === 1) {
yield elements;
} else {
let [first, ...rest] = elements;
for (let perm of permutations(rest)) {
for (let i = 0; i < elements.length; i++) {
let start = perm.slice(0, i);
let rest = perm.slice(i);
yield [...start, first, ...rest];
}
}
}
}
var other = ['A', 'B', 'C'];
var myPermutations = permutations(['X', 'Y', 'Z']);
var done = false;
while (!done) {
var next = myPermutations.next();
if (!(done = next.done)) {
var output = [];
for (var i = 0; i < next.value.length; i++) output.push([other[i], next.value[i]]);
console.log(output);
}
}
You're just looking for permutations. The first elements of your tuples are always the same, the second ones are permuted so that you get all distinct sets of combinations.
const arr1 = ["A","B","C"];
const arr2 = ["Z","Y","X"];
const result = permutate(arr2).map(permutation =>
permutation.map((el, i) => [arr1[i], el])
);
This implementation uses Typescript and Lodash.
const permutations = <T>(arr: T[]): T[][] => {
if (arr.length <= 2)
return arr.length === 2 ? [arr, [arr[1], arr[0]]] : [arr];
return reduce(
arr,
(acc, val, i) =>
concat(
acc,
map(
permutations([...slice(arr, 0, i), ...slice(arr, i + 1, arr.length)]),
vals => [val, ...vals]
)
),
[] as T[][]
);
};
I need to write a program that, when given a list of integers, it finds all 2-pairs of integers that have the same product. i.e. a 2-pair is 2 distinct pairs of integers lets say [(a,b),(c,d)] where a*b = c*d but a ≠ b ≠ c ≠ d.
The range of integers should be from 1 to 1024. What I would like to implement is that when the web page is opened the user is prompted by a pop up in which he will enter the array of integers, i.e [1,2,3,7,8,9,6] etc for instance from the input [1,2,3,7,8,9,6] the output should be [(9,2),(3,6)] since both evaluate to 18.
The coding I did so far is very basic and can be seen below. What I've done so far is the pop-up box alert the input etc, but can't seem to understand how to make the program check for the pairs and give the sum. Thanks in advance to this community who's helping me out to better understand and learn javascript!
I've done my fair bit of research below, definitely different question than mine but have gone through them.
Find a pair of elements from an array whose sum equals a given number
https://www.w3resource.com/javascript-exercises/javascript-array-exercise-26.php
Code:
function evaluate() {
const input = prompt("Please enter the array of integers in the form: 1,2,3,1")
.split(',')
.map(item => item.trim());
function pairs(items) {
}
if (input == "" || input == null) {
document.writeln("Sorry, there is nothing that can be calculated.");
} else {
document.writeln("Your calculation is: ");
document.writeln(pairs(input) + " with a starting input string of: " + input);
}
}
evaluate()
You could iterate the array and a copy of the array beginning by the actual index plus one for getting the products. Store the result in an object with product as key.
Then get the keys (products) of the object, filter it to get only the results with two or more products.
var array = [1, 2, 3, 7, 8, 9, 6],
result = {},
pairs;
array.forEach(function (a, i) {
array.slice(i + 1).forEach(function (b) {
(result[a * b] = (result[a * b] || [])).push([a, b]);
});
});
pairs = Object
.keys(result)
.filter(function (k) { return result[k].length >= 2; })
.map(function(k) { return result[k]; });
console.log(pairs);
We could mutate the equation:
a * b = c * d | : b
a = c * d : b
So actually we just need to get all different combinations of three numbers (b, c, d) and check if the result (a) is also in the given range:
while(true){
// shuffle
const [b, c, d] = items;
const a = c * d / b;
if(items.includes(a + ""))
return true;
}
return false;
Now you only need to shuffle the array to go through all different combinations. You can find an algorithm here
Assuming that you are given an array such as [1,2,3,7,8,9,6] and a value 18 and you need to find pairs that multiply to 18 then, use the following approach
Convert them to a map - O(n)
var inputArr = [1,2,3,7,8,9,6];
var map = inputArr.reduce( (acc, c) => {
acc[ c ] = true; //set any truthy value
return acc;
},{});
Iterate an inputArr and see if its compliment is available in the map - O(n)
var output = [];
var mulValue = 18;
inputArr.forEach( s => {
var remainder = mulValue/s;
if ( map[s] && map[remainder] )
{
output.push( [ s, remainder ] );
map[s] = false;
map[remainder] = false;
}
});
Demo
var inputArr = [1, 2, 3, 7, 8, 9, 6];
var map = inputArr.reduce((acc, c) => {
acc[c] = true; //set any truthy value
return acc;
}, {});
var output = [];
var mulValue = 18;
inputArr.forEach(s => {
var remainder = mulValue / s;
if (map[s] && map[remainder]) {
output.push([s, remainder]);
map[s] = false;
map[remainder] = false;
}
});
console.log(output);
You can try something like this:
Idea:
Loop over the array to compute product. Use this iterator(say i) as get first operand(say op1).
Now again loop over same array but the range will start from i+1. This is to reduce number of iteration.
Now create a temp variable that will hold product and operand.
On every iteration, add value to product in hashMap.
Now loop over hashMap and remove any value that has length that is less than 2.
function sameProductValues(arr) {
var hashMap = {};
for (var i = 0; i < arr.length - 1; i++) {
for (var j = i + 1; j < arr.length; j++) {
var product = arr[i] * arr[j];
hashMap[product] = hashMap[product] || [];
hashMap[product].push([arr[i], arr[j]]);
}
}
for(var key in hashMap) {
if( hashMap[key].length < 2 ) {
delete hashMap[key];
}
}
console.log(hashMap)
}
sameProductValues([1, 2, 3, 7, 8, 9, 6])
I'm getting array of data from server, but after come to jquery datatable i needs multidimention array .Is there any way to make it in jquery itself beflore pass it to datatables ?
My input format is :
["computer","program","laptop","monitor","mouse","keybord","cpu","harddrive"......]
Expected format :
[["computer","program","laptop","monitor"],["mouse","keybord","cpu","harddrive"],[....],[....]........]
Is there any method to parse data format ?
It doesn't take much more than a simple while loop to transform the array.
// This is the original data we get from the server
var input = ["computer","program","laptop","monitor","mouse","keybord","cpu","harddrive"];
// Make a copy of the input, so we don't destroy it
var data = input.slice(0);
// This is our output array
var output = [], group;
// A while loop will transform the plain array into a multidimensional array
while (data.length > 0) {
// Take the first four items
group = data.splice(0, 4);
// Make sure the group contains 4 items, otherwise pad with empty string
while (group.length < 4) {
group.push("");
}
// Push group into the output array
output.push(group);
}
// output = [["computer","program","laptop","monitor"],["mouse","keybord","cpu","harddrive"]]
Update: Beetroot-Beetroot's comment is no longer valid since we create a copy of the input.
I found this beautiful question sometime ago when i had a similar problem. This is a solution based (erm.. ripped out from there) on that :
var a = ["computer", "program", "laptop", "monitor", "mouse", "keybord", "cpu", "harddrive", "tablet"],
n = a.length / 4,
len = a.length,
out = [],
i = 0;
while (i < len) {
var size = Math.ceil((len - i) / n--);
out.push(a.slice(i, i + size));
i += size;
}
alert(JSON.stringify(out));
Message from the future ;) - now we have reduce:
function groupArray(array, groupSize) {
return array.reduce((a, b, i) => {
if (!i || !(i % groupSize)) a.push([])
a.slice(-1).pop().push(b)
return a
}, [])
}
console.log(groupArray(input, 4))
// [
// [ 'computer', 'program', 'laptop', 'monitor' ],
// [ 'mouse', 'keybord', 'cpu', 'harddrive' ]
// ]
I have an A array with n length.
I want to take all possible k (0
for example, if i have A's length is five:
[1,2,3,4,5]
and if k = 3, algorithm must give me B array.
[1,2,3 ]
[1,2, 4 ]
[1,2, 5]
[1, 3,4 ]
[1, 3, 5]
[1, 4,5]
[ 2,3,4 ]
[ 2,3, 5]
[ 2, 4,5]
[ 3,4,5]
Length of B would be equal to n!/k!(n-k)! ('!' means factorial, Newtons method)
I'm using javascript, so in my tags i included it, but it's just algorithm, not necessary written in javascript.
You could do this via a filter method.
In your example you want to receive all permutations of an array, taking a specific number of elements of that array.
You can easily do that in an iterative manner.
Start by taking all permutations of n - 1 elements of an array:
// return all (n - 1) element permutations of an array
var permutations = function(arr) {
return arr.reduce(function(re, value, i) {
// add an array for each element in the original array
return re.concat([arr.filter(function(v, index) {
// drop each element with the same index
return index !== i
})])
}, [])
}
Now permutations([1,2,3]) would return [[1,2], [1,3], [2,3]]
That's always a disjoint set suppose you're having only unique values in the source array.
To receive all 3-element arrays of a 5-element array, you would first calculate the list of 4-element arrays and transform each of them to a 3-element array.
permutations([1,2,3,4]).map(permutations)
=> [[1,2,3] => [[[1,2], [1,3], [2,3]]
,[1,2,4] ,[[1,2], [1,4], [2,4]]
,[1,3,4] ,[[1,3], [1,4], [3,4]]
,[2,3,4] ,[[2,3], [2,4], [3,4]]
] ]
Obviously the problem here is that there are doubles.
That can be solved by dropping all non-unique values.
var unique = function(arr) {
var s = arr.map(function(v) { return "" + v })
return arr.filter(function(v, i) { return s.indexOf("" + v) == i })
}
Packing it all into one function could be done like this:
var permutationsWithLength = function(arr, length) {
var re = [arr]
for (var i = arr.length; i >= length; i--) {
re = re.reduce(function(tmp, perms) {
return unique(temp.concat(permutations(perms)))
}, [])
}
return re
}
I admit that this may not be the fastest approach, especially regarding the unique function, but it's a very generic one and will work for the problem you described even with larger arrays.
Hope it helps ;)
Below is the copy-paste from one of my projects. Don't know if it still works ;)
var choose = function choose_func(elems, len) {
var result = [];
for (var i=0; i<elems.length; i++) {
if (len == 1) {
result.push([elems[i]]);
} else {
var remainingItems = choose_func(elems.slice(i+1, elems.length), len - 1);
for (var j=0; j<remainingItems.length; j++)
result.push([elems[i]].concat(remainingItems[j]));
}
}
return result;
};
var result = choose([1,2,3,4,5], 3)
/*result = [[1,2,3],[1,2,4],[1,2,5],[1,3,4],[1,3,5],
[1,4,5],[2,3,4],[2,3,5],[2,4,5],[3,4,5]] */