Finding all combinations in javascript - javascript

I am creating a game and I need to generate some game pieces. Each piece is an array consisting of 4 numbers(each represents a property of the piece) ranging from 0-2. I need to generate all combinations to get all the game pieces.
So I would need [1, 0, 2, 0], [2, 0, 0, 1], [0, 0, 0, 0], [1, 0, 1, 0] etc..
There should be 81 total combinations of [a, b, c, d] where each variable is a number 0-2.
I am using javascript but any psudocode would be helpful.
Any help is appreciated. Thanks!

Mine
var arr=[];
for (var str,i=0;i<81;i++) {
str = i.toString(3);
arr.push(("000"+str).slice(-4)); // Hmm, I thought slice returned an array.
}
Here is an update taking into account the comments from #katspaugh and #herby
var arr=[];
for (var str,i=81;i<162;i++) {
str = i.toString(3);
arr.push((str).slice(-4).split('').map(Number));
}

If it is a homework, tag it as such.
var BASE = 3, LEN = 4, LIMIT = Math.round(Math.pow(BASE, LEN));
var c = [];
for (var i = 0; i < LIMIT; ++i) {
var item = [];
for (var j = 0, k = i; j < LEN; ++j, k = Math.floor(k/BASE)) {
item.push(k % BASE);
}
c.push(item);
}
Here is a more tricky solution but showing the math behind it better, hopefully:
var BASE = 3, LEN = 4;
var powers = [];
for (var i = 0, LIMIT = 1; i < LEN; ++i, LIMIT *= BASE) {
powers.push(LIMIT);
}
var c = [];
for (i = 0; i < LIMIT; ++i) {
c.push(powers.map(function(basePower) {
return Math.floor(i/basePower) % BASE;
}));
}

var BASE = 3, COMB_LEN = 4
var max = parseInt(new Array(COMB_LEN + 1).join(BASE - 1), BASE),
comb = new Array(COMB_LEN + 1).join(0).split('').map(Number)
var combinations = [], i, n
for (i = 0; i <= max; i++) {
n = i.toString(BASE).split('').map(Number)
combinations.push(
comb.slice(0, COMB_LEN - n.length).concat(n)
)
}

Related

Calculating the GCD for elements in the arrays; JavaScript

I am just starting with JS and need some help with calculating a gcd.
I would like to calculate the gcd for every combination of two elements from two arrays.
I mean: for each element A[i] from array A, for each element B[j] from B, calculate the gcd value of A[i] and B[j] and print it in the console. I do have 16 prints, but they are not correct. I use Euclid's algorithm to calculate it and it looks like the A[i] value is overwritten. I have no idea why. Could someone help me? This is my code:
var n = 4;
var A = [2, 5, 6, 7];
var B = [4, 9, 10, 12];
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
while (A[i] != B[j]) {
if (A[i] < B[j]) {
B[j] = B[j] - A[i];
} else {
A[i] = A[i] - B[j];
}
}
console.log(A[i]);
}
}
You are modifying your array elements while performing euclid's algorithm. I recommend creating a separate function for this algorithm, like:
var n = 4;
var A = [2, 5, 6, 7];
var B = [4, 9, 10, 12];
for (var i = 0; i < n; i++) {
for (var j = 0; j < n; j++) {
console.log(euclid(A[i], B[j]));
}
}
function euclid(a, b) {
while (b != 0) {
var r = a % b;
a = b;
b = r;
}
return a;
}
Edit:
You can make and use a storage array in the following way:
var C = []; // The array that will contain the arrays
for (var i = 0; i < n; i++) {
C[i] = []; // "Inner array"
for (var j = 0; j < n; j++) {
C[i][j] = euclid(A[i], B[j]);
console.log(C[i][j]);
}
}
Without complicationg your algorithm , use forEach as following :
const A = [2, 5, 6, 7];
const B = [4, 9, 10, 12];
const gcd = (x, y) => (!y) ? x : gcd(y, (x % y));
A.forEach((a, i) => {
B.forEach((b, j) => {
console.log(
`GCD(A[${i}]=${a}, B[${j}]=${b}) =`, gcd(a, b)
);
});
})

find all subarrays in o(n) time 1D array using javascript

I want to collect all subarrays for further computation efficiently in javascript. I'm not sure this is possible, but it seems for a subarray sum kadane's formula is o(n) which is more efficient than other methods. But I'm not sure I how I can store the array at each step.
Similar to this quora question, for me the pseudo code was not enough. Thanks for the further breakdown.
another meta link
an example in action of this for [3, 3, 9, 9, 5]
[3], [9], [5], [9, 5], [9, 3], [9, 9], [3, 3],
[3, 9, 9], [3, 3, 9], [9, 9, 5], [3, 3, 9, 9],
[3, 9, 9, 5], [3, 3, 9, 9, 5]
I had done a work previously to calculate all combinations of amino acids total molecular weight. If you neglect the empty one you should have 2^n - 1 sub arrays. So there is no O(n) here. I've got two methods as binary and recursive.
function getSubArrays(arr){
var len = arr.length,
subs = Array(Math.pow(2,len)).fill();
return subs.map((_,i) => { var j = -1,
k = i,
res = [];
while (++j < len ) {
k & 1 && res.push(arr[j]);
k = k >> 1;
}
return res;
}).slice(1);
}
console.log(JSON.stringify(getSubArrays([1,2,3,4,5])));
function getSubArrays(arr){
if (arr.length === 1) return [arr];
else {
subarr = getSubArrays(arr.slice(1));
return subarr.concat(subarr.map(e => e.concat(arr[0])), [[arr[0]]]);
}
}
console.log(JSON.stringify(getSubArrays([1,2,3,4,5])));
I couldn't manage to get subarrays of an array with more than 23 items though.
Here are the performances. To be on the safe side i try with 22 items, first with recursive and then with binary route.
function getSubArrays(arr){
if (arr.length === 1) return [arr];
else {
subarr = getSubArrays(arr.slice(1));
return subarr.concat(subarr.map(e => e.concat(arr[0])), [[arr[0]]]);
}
}
var aminos = Array(22).fill().map((_,i) => i+1),
subarrs = [],
ps = 0,
pe = 0;
ps = performance.now();
subarrs = getSubArrays(aminos);
pe = performance.now();
console.log("recursive route took: " + (pe-ps) + "msec to produce " + subarrs.length + " sub arrays");
function getSubArrays(arr){
var len = arr.length,
subs = Array(Math.pow(2,len)).fill();
return subs.map((_,i) => { var j = -1,
k = i,
res = [];
while (++j < len ) {
k & 1 && res.push(arr[j]);
k = k >> 1;
}
return res;
}).slice(1);
}
var aminos = Array(22).fill().map((_,i) => i+1),
subarrs = [],
ps = 0,
pe = 0;
ps = performance.now();
subarrs = getSubArrays(aminos);
pe = performance.now();
console.log("binary route took: " + (pe-ps) + "msec to produce " + subarrs.length + " sub arrays");
This is fairly simple to do: https://jsfiddle.net/j1LuvxLq/
All you do is iterate possible lenghts and starting points and just print out the subsets. Complexity is O(n²) where n is the length of the original array. No way to improve it thought because that's the order of how many subsets there are.
var set = [3, 3, 9, 9, 5].join('')
var set_length = set.length
var subsets = []
for (var length_of_subset = 1; length_of_subset <= set_length; length_of_subset++) {
for (var start_of_subset = 0; start_of_subset <= set_length - length_of_subset; start_of_subset++) {
var current_subset = set.substring(start_of_subset, start_of_subset + length_of_subset)
if(subsets.indexOf(current_subset) == -1) {
subsets.push(current_subset.split(''))
}
}
}
// print the subsets out
for (s in subsets) {
$('body').append(subsets[s].join(', ') + '<br>')
}
Alternative, possibly nicer solution would be to use dynamic programming. Start with 3 and either remove last element or add next element. Check it out here: https://jsfiddle.net/p82fcs4m/
var set = [3, 3, 9, 9, 5].join('')
var subsets = []
take(set[0], set.substring(1))
function take(chosen, left) {
if(subsets.indexOf(chosen) != -1) {
return
}
subsets.push(chosen)
if (chosen.length > 1) {
take(chosen.substring(1), left)
}
if (left.length > 0) {
take(chosen.concat(left[0]), left.substring(1))
}
}
$('body').append(subsets.join('<br>'))
Try this:
function getSubArrays(arr) {
const subArrays = [];
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i; j++) {
const subArray = arr.slice(i, j + i + 1);
subArrays.push(subArray);
}
}
}
Still O(n²) tho
I believe using Array.slice is the most clean way to do it, isn't it?
function getSubArrays(arr) {
const subArrays = [];
for (var i = 0; i < arr.length; i++) {
for (var j = i; j < arr.length; j++) {
subArrays.push(arr.slice(i, j + 1));
}
}
return subArrays;
}

Sort an array containing numbers using a 'for' loop

I am new to JavaScript, and I have an array which contains numbers.
var arr = [2,4,8,1,5,9,3,7,6];
How can I sort it using a native for loop in JavaScript?
I know sort function is available, but I want it through for loop.
The output should be:
var res = [1,2,3,4,5,6,7,8,9];
var Arr = [1, 7, 2, 8, 3, 4, 5, 0, 9];
for (var i = 1; i < Arr.length; i++)
for (var j = 0; j < i; j++)
if (Arr[i] < Arr[j]) {
var x = Arr[i];
Arr[i] = Arr[j];
Arr[j] = x;
}
console.log(Arr);
I would do something like this...
var input = [2,3,8,1,4,5,9,7,6];
var output = [];
var inserted;
for (var i = 0, ii = input.length ; i < ii ; i++){
inserted = false;
for (var j = 0, jj = output.length ; j < jj ; j++){
if (input[i] < output[j]){
inserted = true;
output.splice(j, 0, input[i]);
break;
}
}
if (!inserted)
output.push(input[i])
}
console.log(output);
Maybe there are more efficient ways, but if you want to use the for loop, it's my first idea...
First create an empty array where the sorted numbers will be pushed into.
let sorted = [];
Secondly, create a very large amount of numbers that none of the numbers of the array can match. This number will be used for the very first comparison to determine which number of the array is smaller.
let comparison = 9000000000;
Create a for loop.
This loop will have another loop inside of it. The inner loop will check for the smallest number in a given array, and once the smallest number is gotten, it will be push into the empty array we created. The smallest number will also be removed from the initial array and then the array will run again.
for(a = 0; a < arr.length; a++){
//This inner loop fetches the smallest number.
for(b = 0; b < arr.length; a++){
if(comparison > arr[b]){
comparison = arr[b];
}
}
// The smallest number is assigned to comparison
// Now it being pushed to the empty array
sorted.push(comparison);
// Remove the smallest number from the initial array
let indexOfSmallNumber = arr.indexOf(comparison);
arr.splice(indexOfSmallNumber, 1);
// Set the comparison back to 9000000000;
comparison = 90000000000;
a = -1;
// Here, "a" is our main loop index counter and we are
// setting it to -1 because we don't want it to change
// to 2 by default, doing this will make the loop run
// forever until the initial array is empty.
}
let arr = [4, 2, 5, 1]
let temp;
function converter(arr) {
for(let i=0; i<arr.length; i++) {
for (let j=i+1; j<arr.length; j++) {
if(arr[i] > arr[j]) {
temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
}
return arr
}
const newArr = converter(arr)
console.log(newArr)
Use:
let s = [4, 6, 3, 1, 2];
for (let i = 0; i < s.length;) {
if (s[i] > s[i + 1]) {
let a = s[i];
s[i] = s[i + 1];
s[i + 1] = a;
i--;
}
else {
i++;
}
}
This is a sorting algorithm which has a best time complexity of O(n) and the worst time of O(n^2).
This code checks for each number, and then compares to all numbers on the left side.
To check the time it takes each code to run, you can also use this code below:
let start = process.hrtime.bigint()
let end = process.hrtime.bigint()
console.log(end - start) // This measures the time used in nano seconds.
Also for microseconds, you can use this performance.now().
Here there is a very simple solution that uses a temporary array to store the values greater than the current one. Then it puts the current value between the lesser and the greater values:
var arr = [2,4,8,1,5,9,3,7,6];
var res = [];
for (const c of arr) {
let tmp = [];
while (c < res[res.length-1]) {
tmp.unshift(res.pop());
}
res = [...res, c, ...tmp];
}
const numberArr = [5, 9, 2, 8, 4, 10, 1, 3, 7, 6];
function sortedFunction(arr) {
let sortedArr = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
let n = 0;
if (arr[i] > arr[j]) {
n = arr[i];
arr[i] = arr[j];
arr[j] = n;
}
}
sortedArr.push(arr[i]);
}
return sortedArr;
}
sortedFunction(numberArr);
Under the JavaScript array sort section of W3Schools it talks about how to compare a value in an array with the others and then order them based on the values being returned. I updated the code to use a for loop to sort values.
// Ascending points
var points = [5.0, 3.7, 1.0, 2.9, 3.4, 4.5];
var output = [];
var i;
for (i = 0; i < points.length; i++) {
points.sort(function (a, b) {
return a - b
});
output += points[i] + "<br>";
}
console.log(output);
// Descending points
var points = [5.0, 3.7, 1.0, 2.9, 3.4, 4.5];
var output = [];
var i;
for (i = 0; i < points.length; i++) {
points.sort(function (a, b) {
return b - a
});
output += points[i] + "<br>";
}
console.log(output);
const array = [12, 3, 45, 61, 23, 45, 6, 7];
function sortArray(array) {
for (var i = 0; i < array.length; ++i) {
for (var j = 0; j < array.length - 1 - i; ++j) {
if (array[j] > array[j + 1]) {
[array[j], array[j + 1]] = [array[j + 1], array[j]];
}
}
}
return array;
}
console.log(sortArray(array));
Here are the two solutions for the same algorithm:
Solution 1:
We can directly use JavaScript functions:
let arr = [2, 4, 8, 1, 5, 9, 3, 7, 6]
const changeOrder = (arr) => {
return arr.sort((a, b) => a - b)
}
let result = changeOrder(arr);
console.log(result) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
Solution 2:
We can use a JavaScript for loop for doing the same
let arr = [2, 4, 8, 1, 5, 9, 3, 7, 6]
const changeOrder = (arr) => {
for(let i=1; i< arr.length; i++) {
for(let j=0; j < i; j++) {
if(arr[i] < arr[j]) {
let x = arr[i]
arr[i] = arr[j]
arr[j] = x
}
}
}
return arr;
}
let result = changeOrder(arr);
console.log(result) // [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
An improvement to previous answer
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}

Javascript - How to push an array to a multidimensional array

I trying to push an array I've generated to a multidimensional array, and for some reason the value of all the other positions in the array's values, are the same as the value I just pushed.
For example: I do
var grades = [];
for(var i = 0; i < num_qes + 1; i++){
var grade = [0, 0, 0, 0];
grade[0] = i;
for(var n = 0; n < num_qes+ 1; n++){
grade[1] = n;
for(var f = 0; f < num_qes+ 1; f++){
grade[2] = f;
for(var t = 0; t < num_qes+ 1; t++){
grade[3] = t;
allGrad = grade[0] + grade[1] + grade[2] + grade[3];
//println(allGrad);
if(allGrad === num_qes){
grades.push(grade);
}
}
}
}
Here at the end I check to see if all of the values in my generated array are exactly equal to the number of questions.
if(allGrad === num_qes){
grades.push(grade);
}
Let's say that grade = [9, 1, 0, 0], when I push this value to the multidimensional array, grades, all the values change to [9, 1, 0, 0]. So the multidimensional array looks like this: [[9, 1, 0, 0], [9, 1, 0, 0], [9, 1, 0, 0]], when it SHOULD look like this: [[9, 0, 0, 1], [9, 0, 1, 0], [9, 1, 0, 0]].
I hope what I said make senses, and thanks in advance for ansnewing.
The jsfiddle is right here
Is this what you are after?
var grades = [];
var num_qes = 4;
for(var i = 0; i <= num_qes; i++){
for(var n = 0; n <= num_qes; n++){
for(var f = 0; f <= num_qes; f++){
for(var t = 0; t <= num_qes; t++){
var sum = i + n + f + t;
if(sum === num_qes){
console.log(i + ',' + n + ',' + f + ',' + t);
var grade = [i, n, f, t];
grades.push(grade);
}
}
}
}
}
Notes:
I've replaced i < num_qes + 1 with i <= num_ques for simplicity
Only creating the grade array in the inner loop when your condition is met (makes it much more readable)
Summing the numbers directly rather than reading from the grade array you've just populated (again more readable)
Using console.log() to output results that match criteria
Results in console look like this...
0,0,0,4
0,0,1,3
0,0,2,2
0,0,3,1
0,0,4,0
0,1,0,3
0,1,1,2
0,1,2,1
0,1,3,0
etc

How to slice an array in a custom pattern?

I have this array:
var x = [1,2,3,4,5,"a","b","c",9,10];
I would like to slice this array into this pattern:
var x = [[1,2,3],[2,3,4],[3,4,5],[4,5,"a"],[5,"a","b"],["a","b","c"],["b","c",9],["c",9,10]];
I used the following code and been able to get [[1,2,3],[4,5,"a"],["b","c",9],[10,11,12]] . But it doesn't work for me. I need to get the pattern above.
var stream = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var x = ["a", "b", "c"];
var ad_time = 6;
var result = [];
var ad_index = stream.indexOf(ad_time);
if (~ad_index) {
for (var i = 0; i < x.length; i++) {
stream[ad_index + i] = x[i];
}
}
while (stream.length > 0) {
var chunk = stream.splice(0, 3);
result.push(chunk);
}
console.log(JSON.stringify(result));
Thanks in advence!
This code should do it:
var x = [1,2,3,4,5,"a","b","c",9,10];
var new_array = [];
for (var i = 0; i < x.length - 2; i++) {
new_array.push(x.slice(i, i + 3));
}
You can achieve it with a simple for loop:
var x = [1,2,3,4,5,"a","b","c",9,10];
var result = [];
for (var i = 0, il = x.length - 2; i < il; i++) {
result.push([x[i], x[i + 1], x[i + 2]]);
}
console.log(result);
EDIT: Array.slice() is more elegant, however it is much slower. On Chrome it is 80% - 85% slower according to this test. If you don't need to worry about performance, choose whichever you like. For example if you need to slice 8 elements from the array, then using x.slice(i + 8) is easier to write and read than [x[i], x[i + 1], x[i + 2], x[i + 3], ...]. However if performance matters, then direct access might be a better choice.

Categories