Shuffle an array made in a for loop - javascript

jsfiddle
var test = [1, 2, 3, 4, 5]
var Quiz = [];
for (var i=0; i<5; i++){
shuffle(test)
Quiz[i] = {
options: [],
correct: Math.floor((Math.random() * 5) + 1)
};
for(quizS of Quiz){
quizS.options.push = test
}
}
console.log(Quiz);
function shuffle(arra1){
var ctr = arra1.length, temp, index;
while (ctr > 0) {
index = Math.floor(Math.random() * ctr);
ctr--;
temp = arra1[ctr];
arra1[ctr] = arra1[index];
arra1[index] = temp;
}
return arra1;
}
So I am trying to create an array (Quiz) through a for loop where each individual array has its own randomized order from a certain array (test).
What I'm getting in the console log is the same randomized order across all arrays. How do I randomize/shuffle it for each separate array?

Here is your required solution:
You have to clone the array inorder to assign it without changing the original array
use, slice(0) to clone array.
var a = shuffle(test).slice(0)
var test = [1, 2, 3, 4, 5]
var Quiz = [];
var random = {};
function shuffle(arra1) {
var ctr = arra1.length, temp, index;
while (0 !== ctr) {
index = Math.floor(Math.random() * ctr);
ctr -= 1
temp = arra1[ctr];
arra1[ctr] = arra1[index];
arra1[index] = temp;
}
return arra1;
}
for (var i = 0; i < 5; i++) {
var a = shuffle(test).slice(0)
Quiz.push({
options: a,
riktig: Math.floor((Math.random() * 5) + 1)
});
}
console.log(Quiz);
Please run the above snippet
Here is a DEMO plunker for the same

Related

JavaScript: calculate the average of an odd number

I want to count the average value of the odd numbers from a list of numbers. I have a starting code to count the average, but I don't know how can I choose only the odd numbers from the list?
Here is my code:
var numberArray = [1,2,3,4,5,6], thisTotal=0,thisAverage=0;
for (var i=0; i<numberArray.length; i++) {
thisTotal += numberArray[i];
}
thisAverage = (thisTotal/numberArray.length);
alert(thisAverage)
You can use a filter function to return only the odd numbers:
var oddArray = numberArray.filter(function(val) {
return val % 2 !== 0;
});
Full example:
var numberArray = [1, 2, 3, 4, 5, 6];
var thisTotal = 0;
var thisAverage = 0;
var oddArray = numberArray.filter(function(val) {
return val % 2 !== 0;
});
console.log(oddArray); // [1, 3, 5]
var thisTotal = oddArray.reduce(function(accumulator, currentValue) { return accumulator + currentValue;
});
console.log(thisTotal); // 1 + 3 + 5 => 9
var thisAverage = thisTotal / oddArray.length;
console.log(thisAverage); // 9 / 3 => 3
var numberArray=[1,2,3,4,5,6], thisAverage=0,oddlength=0;
for(var i=0;i<numberArray.length;i++)
{
if(numberArray[i]%2!==0){
thisAverage+=numberArray[i];
oddlength++;
}
}
thisAverage=(thisAverage/oddlength);
alert(thisAverage)
Well, you can get what you want by this.
var numberArray=[1,2,3,4,5,6], thisTotal=0,thisAverage=0;
for(var i=0; i < 3; i++) {
thisTotal += numberArray[i * 2];
thisAverage= (thisTotal/numberArray.length);
}
console.log(thisAverage);
or if you want general solution, use this.
var numberArray=[1,2,3,4,5,6,7,8,...on and on], thisTotal=0,thisAverage=0;
for(var i=0; i < Math.ceil(numberArray.length() / 2); i++) {
thisTotal += numberArray[i * 2];
thisAverage= (thisTotal/numberArray.length);
}
console.log(thisAverage);
hope my code be helpful :)
You can use the function reduce to add and count.
var numberArray = [1, 2, 3, 4, 5, 6],
result = numberArray.reduce((a, n) => {
if (n % 2 !== 0) {
a.sum += n;
a.count++;
}
return a;
}, {sum: 0, count: 0}),
average = result.sum / result.count;
console.log(average);
Assuming the numbers are in an array, you can do this:
var numbers = [1, 2, 3, 4, 5, 6];
var info = numbers.filter(function(n) { return n % 2 !== 0})
.reduce(function(acc, item) {
return {sum: acc.sum + item, count: acc.count + 1}
}, {sum: 0, count: 0});
var avg = info.sum / info.count;
This example uses filter and reduce methods, which are declarative and more clear.
filter returns a new array with the items for which the function returns true, and then reduce, for each item, updates an 'accumulator'. The accumulator can be anything, and in this case is an object with the sum of the numbers and their count. For each item, we add add the current number to the sum property and add 1 to count. Finally, we just devide sum by count and done.
var acc = 0, oddCount = 0;
for(var i = 0; i < numberArray.length; i++) {
if(numberArray[i] % 2 !== 0) {
acc += numberArray[i];
oddCount++;
}
}
return acc / oddCount;
You can create a new array and store odd values in that array and after that you can apply your logic to that array.
var a=[1,2,3,4,5,6,10,11];
var ar=[];
for (var i = 0; i < a.length; i++) {
if(a[i] % 2 !== 0) {
ar.push(a[i]);
}
}
console.log(ar);
var numberArray=[1,2,3,4,5,6,7,8];
var count = 0;
var result = 0;
for (let i = 0; i <= (numberArray.length-1); i++)
{
if (numberArray[i] % 2 != 0)
{
result += numberArray[i];
count++;
}
}
alert(result / count);

Iterate through an array and back once it reaches the end

What I want
I am trying to iterate through an array from the start (logging all the elements) then once the end is reached, go back through the array. Once it has reached the start again, it will go through the array again. It will do this forever.
Example:
Array = [1, 2, 3, 4, 5]
Log: 1, 2, 3, 4, 5, 4, 3, 2, 1, 2, 3...
What I have tried
This is what I have tried:
let a = 0;
let dir = -1;
let arr = new Array();
function setup() {
for (let i = 0; i < 10; i++) {
arr.push(i);
}
}
function draw() {
for (let el of arr) {
console.log(el);
}
if (i >= arr.length || i <= 0) {
dir *= -1;
}
i += dir;
}
If you are unaware, this is a p5.js sketch. The setup() function runs on the page load and the draw() function runs repetitively.
What happened
This is what happened
stop_count is for testing only, preventing it loops forever.
let arr = [1,2,3,4,5];
let dir = 1;
let stop_count = 0;
while (stop_count <10) {
let i;
i = dir===1 ? 0 : arr.length-1;
console.log(arr[i]);
i+=dir;
while (i < arr.length-1 && i >=1){
console.log(arr[i]);
i+=dir;
}
dir = dir*-1;
stop_count += 1;
}
You can use array functions such as concat, map, slice,reverse and forEach or map instead of looping:
var arr = [1,2,3,4,5];
var upDown = arr.concat(
//not the last one or 5 will be logged twice
arr.slice(0,-1)
//reverse order
.reverse()
);
upDown.forEach(
item=>console.log(item)
);
Your draw function can look like this:
var draw =(function(){
var arr = [1,2,3,4,5];
var upDown = arr.concat(
arr.slice(0,-1)
.reverse()
);
var index = -1;
return function(){
index = (index===upDown.length-1)
? 0
: index+1;
console.log(upDown[index]);
}
}());//IIFE to set up upDown array and index

Parse array to equal intervals JS

I want to parse my array to 4 equal intervals. For example, array [12, 48] parse to 4 intervals [12,21], [21, 30], [30, 39], [39, 48]. I could only parse my Array to pairs (code here). But I don't know how to do what I want.
var arrayTest = [];
for (var i = 0; i < 1000; i++) arrayTest[i] = i;
var ab = [2, 6];
start = ab[0];
finish = ab[1];
var ab_new = [];
for (var i = start; i <= finish; i++) ab_new[i]= arrayTest[i];
var output = [];
for (var i = start; i < ab_new.length - 1; ++i) {
output[i] = [];
output[i].push(ab_new[i]);
output[i].push(ab_new[i + 1]);
}
console.log(output);
My output is:
[ , , [ 2, 3 ], [ 3, 4 ], [ 4, 5 ], [ 5, 6 ] ]
You can calculate the interval and use it to map in an array of length 4 over the index.
const ab = [12, 48]
const start = ab[0];
const end = ab[1];
const interval = (end - start) / 4;
const out = Array(4)
.fill()
.map((_, i) => [start + i*interval, start + (i + 1) * interval])
You could take a length for each interval and add the lenght to the start value for each part.
function getIntervals(range, parts) {
var result = [],
length = (range[1] - range[0]) / parts,
i = 0,
t;
while (i < parts) {
t = range[0] + i * length;
result.push([t, t + length]);
i++;
}
return result;
}
console.log(getIntervals([12, 48], 4));
Another approach by using length as increment value.
function getIntervals(range, parts) {
var result = [],
length = (range[1] - range[0]) / parts,
i = range[0];
while (i < range[1]) {
result.push([i, i += length]);
}
return result;
}
console.log(getIntervals([12, 48], 4));
ES6
function getIntervals(range, parts) {
var l = (range[1] - range[0]) / parts,
i = range[0];
return Array.from({ length: parts}, _ => [i, i += l]);
}
console.log(getIntervals([12, 48], 4));
let a=[12,48]; // your array
var interval = 4;
var diff =(a[1]-a[0])/interval; // calculating the diff
var start = a[0]; //start value
var b =[]; // output array
for(var i=0; i<interval; i++){
b.push( [start, start + diff]); // for each iteration push start and start+diff
start+=diff;
}
console.log(b)
function sep4(inp){
var diff = inp[1] - inp[0]
var add = diff/4
var ar = []
for(i = 1; i < 5; i++){
ar.push([inp[0], inp[0] + (add * i)])
}
return ar
}
// just call the function as sep4([12, 48])

Shuffle multidimensional array in javascript gets duplicated

I have a problem with shuffling an array in javascript.
A multidimensional array gets its row shuffled twice and the result is EXACT same numbers returned.
I do not want same numbers, but I want different shuffled results.
this.pairs = [
[0, 1, 2, 3]
];
this.shuffled = [
[shuffle(this.pairs[0])],
[shuffle(this.pairs[0])]
];
console.log(this.shuffled);
Where shuffle function is:
function shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;}
It just randomized the array values.
Now when I try shuffle([0,1,2,3]) it works if I just call the same function twice.
But when I write shuffle(this.pairs[0]); it returns exact same values no matter how many times I call it. Any help?
UPDATE
I then tried as suggested to add them in different variables, still does not work.
this.pairs = [
[0, 1],
[0, 1]
];
var level1 = this.pairs[0];
var level2 = this.pairs[0];
this.shuffled = [
shuffle(level1),
shuffle(level2)
];
console.log(this.shuffled);
Same goes for this:
this.pairs = [
[0, 1],
[0, 1]
];
var level1 = shuffle(this.pairs[0]);
var level2 = shuffle(this.pairs[0]);
this.shuffled = [
level1,
level2
];
console.log(this.shuffled);
The issue is you are using this.name,
It will point to same reference always
So result will be overridden by last shuffle call.
So you need to copy the value after each shuffling to a new variable.
function shuffleMultiArray(multArr) {
for (let i = 0; i < multArr.length; i++) {
for (let j = 0; j < multArr[i].length; j++) {
let i1 = Math.floor(Math.random() * (multArr.length));
let j1 = Math.floor(Math.random() * (multArr.length));
let temp = multArr[i][j];
multArr[i][j] = multArr[i1][j1];
multArr[i1][j1] = temp;
}
}
}
Try to assign shuffle function result to a variable.

Output each combination of an array of numbers with javascript

I have several numbers in an array
var numArr = [1, 3, 5, 9];
I want to cycle through that array and multiply every unique 3 number combination as follows:
1 * 3 * 5 =
1 * 3 * 9 =
1 * 5 * 9 =
3 * 5 * 9 =
Then return an array of all the calculations
var ansArr = [15,27,45,135];
Anyone have an elegant solution? Thanks in advance.
A general-purpose algorithm for generating combinations is as follows:
function combinations(numArr, choose, callback) {
var n = numArr.length;
var c = [];
var inner = function(start, choose_) {
if (choose_ == 0) {
callback(c);
} else {
for (var i = start; i <= n - choose_; ++i) {
c.push(numArr[i]);
inner(i + 1, choose_ - 1);
c.pop();
}
}
}
inner(0, choose);
}
In your case, you might call it like so:
function product(arr) {
p = 1;
for (var i in arr) {
p *= arr[i];
}
return p;
}
var ansArr = [];
combinations(
[1, 3, 5, 7, 9, 11], 3,
function output(arr) {
ansArr.push(product(arr));
});
document.write(ansArr);
...which, for the given input, yields this:
15,21,27,33,35,45,55,63,77,99,105,135,165,189,231,297,315,385,495,693
I think this should work:
var a = [1, 3, 5, 9];
var l = a.length;
var r = [];
for (var i = 0; i < l; ++i) {
for (var j = i + 1; j < l; ++j) {
for (var k = j + 1; k < l; ++k) {
r.push(a[i] * a[j] * a[k]);
}
}
}
Edit
Just for my own edification, I figured out a generic solution that uses loops instead of recursion. It's obvious downside is that it's longer thus slower to load or to read. On the other hand (at least on Firefox on my machine) it runs about twice as fast as the recursive version. However, I'd only recommend it if you're finding combinations for large sets, or finding combinations many times on the same page. Anyway, in case anybody's interested, here's what I came up with.
function combos(superset, size) {
var result = [];
if (superset.length < size) {return result;}
var done = false;
var current_combo, distance_back, new_last_index;
var indexes = [];
var indexes_last = size - 1;
var superset_last = superset.length - 1;
// initialize indexes to start with leftmost combo
for (var i = 0; i < size; ++i) {
indexes[i] = i;
}
while (!done) {
current_combo = [];
for (i = 0; i < size; ++i) {
current_combo.push(superset[indexes[i]]);
}
result.push(current_combo);
if (indexes[indexes_last] == superset_last) {
done = true;
for (i = indexes_last - 1; i > -1 ; --i) {
distance_back = indexes_last - i;
new_last_index = indexes[indexes_last - distance_back] + distance_back + 1;
if (new_last_index <= superset_last) {
indexes[indexes_last] = new_last_index;
done = false;
break;
}
}
if (!done) {
++indexes[indexes_last - distance_back];
--distance_back;
for (; distance_back; --distance_back) {
indexes[indexes_last - distance_back] = indexes[indexes_last - distance_back - 1] + 1;
}
}
}
else {++indexes[indexes_last]}
}
return result;
}
function products(sets) {
var result = [];
var len = sets.length;
var product;
for (var i = 0; i < len; ++i) {
product = 1;
inner_len = sets[i].length;
for (var j = 0; j < inner_len; ++j) {
product *= sets[i][j];
}
result.push(product);
}
return result;
}
console.log(products(combos([1, 3, 5, 7, 9, 11], 3)));
A recursive function to do this when you need to select k numbers among n numbers. Have not tested. Find if there is any bug and rectify it :-)
var result = [];
foo(arr, 0, 1, k, n); // initial call
function foo(arr, s, mul, k, n) {
if (k == 1) {
result.push(mul);
return;
}
var i;
for (i=s; i<=n-k; i++) {
foo(arr, i+1, mul*arr[i], k-1, n-i-1);
}
}
This is a recursive function.
First parameter is array arr.
Second parameter is integer s. Each call calculates values for part of the array starting from index s. Recursively I am increasing s and so array for each call is recursively becoming smaller.
Third parameter is the value that is being calculated recursively and is being passed in the recursive call. When k becomes 1, it gets added in the result array.
k in the size of combination desired. It decreases recursively and when becomes 1, output appended in result array.
n is size of array arr. Actually n = arr.length
var create3Combi = function(array) {
var result = [];
array.map(function(item1, index1) {
array.map(function(item2, index2) {
for (var i = index2 + 1; i < array.length; i++) {
var item3 = array[i];
if (item1 === item2 || item1 === item3 || item2 === item3 || index2 < index1) {
continue;
}
result.push([item1, item2, item3]);
}
});
});
return result;
};
var multiplyCombi = function(array) {
var multiply = function(a, b){
return a * b;
};
var result = array.map(function(item, index) {
return item.reduce(multiply);
});
return result;
}
var numArr = [1, 3, 5, 9];
// create unique 3 number combination
var combi = create3Combi(numArr); //[[1,3,5],[1,3,9],[1,5,9],[3,5,9]]
// multiply every combination
var multiplyResult = multiplyCombi(combi); //[15,27,45,135];
https://github.com/dankogai/js-combinatorics
Found this library. Tested to be working. Below is from the library document:
var Combinatorics = require('js-combinatorics');
var cmb = Combinatorics.combination(['a','b','c','d'], 2);
while(a = cmb.next()) console.log(a);
// ["a", "b"]
// ["a", "c"]
// ["a", "d"]
// ["b", "c"]
// ["b", "d"]
// ["c", "d"]
Using node, you can do this pretty easily using a library. First install bit-twiddle using npm:
npm install bit-twiddle
Then you can use it in your code like this:
//Assume n is the size of the set and k is the size of the combination
var nextCombination = require("bit-twiddle").nextCombination
for(var x=(1<<(k+1))-1; x<1<<n; x=nextCombination(x)) {
console.log(x.toString(2))
}
The variable x is a bit-vector where bit i is set if the ith element is contained in the combination.

Categories

Resources