Can you please take a look at this code and let me know why the storage.push(players) instead of adding new array/set of players into storage is merging them with previously added array?
Technically what I am expecting here is getting something like this
[
[2,52,35,16,18,46],
[18,44,66,25,78,26]
]
but what I am getting now is only one array in storage like
[
[2,52,35,16,18,46,18,44,66,25,78,26]
]
var storage = [];
var players = [];
function createplayers(arr) {
for (let i = 0; i < 8; i++) {
let a = true,
n;
while (a) {
n = Math.floor(Math.random() * 100) + 1;
a = arr.includes(n);
}
arr.push(n);
}
}
var x = 3;
var interval = 1000;
for (var i = 0; i < x; i++) {
setTimeout(function() {
createplayers(players);
storage.push(players)
console.log(players)
console.log(storage)
}, i * interval)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Your had only one players array all the time. Move the array creation to createplayers().
var storage = [];
function createplayers() {
var arr = [];
for (let i = 0; i < 8; i++) {
let a = true,
n;
while (a) {
n = Math.floor(Math.random() * 100) + 1;
a = arr.includes(n);
}
arr.push(n);
}
return arr;
}
var x = 3;
var interval = 1000;
for (var i = 0; i < x; i++) {
setTimeout(function() {
var players = createplayers();
storage.push(players)
console.log(players)
console.log(storage)
}, i * interval)
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
This Question has nothing to do with jQuery
You have to clear the players array everytime you add to storage.
Here is the solution
var storage = [];
var players = [];
function createplayers(arr) {
for (let i = 0; i < 8; i++) {
let a = true,
n;
while (a) {
n = Math.floor(Math.random() * 100) + 1;
a = arr.includes(n);
}
arr.push(n);
}
}
var x = 3;
var interval = 1000;
for (var i = 0; i < x; i++) {
setTimeout(function() {
createplayers(players);
storage.push(players)
console.log(players)
//Notice this line
players=[];
console.log(storage)
}, i * interval)
}
Related
I have an array list I loop over and modify it each time. I want to store all instances of my list array in an other array I named allLists, and to do so, I'm using the slice method.
It seems to work in the simple example below:
let list=[1,2,3,4];
let allList = [];
allList.push(list.slice());
list[2]=6;
allList.push(list.slice());
console.log(allList);// returns [1,2,3,4] [1,2,6,4]
But it doesn't work in the following code. Instead, allLists is filled with the last instance of the list array.
let list = Array.from({
length: 9
}, () => Array.from({
length: 9
}, () => [1, 2, 3, 4, 5, 6, 7, 8, 9]));
let allLists = [list.slice()];
let indexList = [];
let lengthList = [];
let key = true;
function handleNewIndex(list) {
let newIndex = [0, 0];
let maxLength = 9;
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length < maxLength && list[i][j].length > 0) {
maxLength = list[i][j].length;
newIndex = [i, j];
}
}
}
return newIndex;
}
function isSudokuValid(list) {
for (let i = 0; i < list.length; i++) {
for (let j = 0; j < list.length; j++) {
if (list[i][j].length === 0) {
return false;
}
}
}
return true;
}
function handleWrongSudoku(allLists, indexList, lengthList) {
let counter = 1;
while (lengthList[lengthList.length - counter] <= 1) {
counter = counter + 1;
allLists.pop();
indexList.pop();
}
let wrongList = allLists.pop();
list = allLists.pop();
indexLine = indexList[indexList.length - 1][0];
indexColumn = indexList[indexList.length - 1][1];
let wrongNumber = wrongList[indexLine][indexColumn];
for (let i = 0; i < list[indexLine][indexColumn].length; i++) {
if (list[indexLine][indexColumn][i] != wrongNumber) {
list[indexLine][indexColumn] = list[indexLine][indexColumn][i];
}
}
allLists.push(list.slice());
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
function generateSudoku() {
let indexLine = Math.floor(Math.random() * 9);
let indexColumn = Math.floor(Math.random() * 9);
let counter = 0;
while (counter < 81) {
indexList.push([indexLine, indexColumn]);
let bigSquareIndex = 3 * Math.floor(indexLine / 3) + Math.floor(indexColumn / 3);
lengthList.push(list[indexLine][indexColumn].length);
list[indexLine][indexColumn] = list[indexLine][indexColumn][Math.floor(Math.random() * list[indexLine][indexColumn].length)];
counter = counter + 1;
for (let i = 0; i < 9; i++) {
for (let j = 0; j < 9; j++) {
if (3 * Math.floor(i / 3) + Math.floor(j / 3) === bigSquareIndex) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
} else if (i === indexLine || j === indexColumn) {
let k = 0;
let n = list[i][j].length;
while (list[i][j][k] != list[indexLine][indexColumn] && k < n) {
k = k + 1;
}
if (k < n) {
list[i][j].splice(k, 1);
}
}
}
}
allLists.push(list.slice());
key = isSudokuValid(list);
if (key === false) { //ignore this scenario, not done yet, assume key = true at all time
console.log(key, lengthList, indexList, allLists);
handleWrongSudoku(allLists, indexList, lengthList);
key = true;
//return;
} else {
indexLine = handleNewIndex(list)[0];
indexColumn = handleNewIndex(list)[1];
}
}
}
generateSudoku();
console.log(allLists); // returns 81 times the same 9x9 array instead of the 81 different instances of the list array
I don't know what I'm doing wrong here.
Thanks for the hint Code Maniac.
I used the JSON method instead to create a deep copy and it's working fine now.
allLists.push(JSON.parse(JSON.stringify(list)));
This post explains the difference between shallow and deep copy:
https://www.freecodecamp.org/news/how-to-clone-an-array-in-javascript-1d3183468f6a/
The exercise is as follows, given an array with multiple arrays inside, return the sum of the product subtraction with the LMC. I managed to create the code, but is passing 12000ms of response and wanted to optimize my code, I still have difficulty with it, can you help me? Follow the code below.
The expected result is 840.
let pairs = [[15,18], [4,5], [12,60]];
function sumDifferencesBetweenProductsAndLCMs (pairs)
{
let product = [];
let prodResult = 1;
let LMC = [];
let result = 0;
// take a product
for(let i = 0; i < pairs.length;i++)
{
for(let j = 0; j < pairs[i].length;j++)
{
prodResult *= pairs[i][j]
}
product.push(prodResult);
if(prodResult != 0)
{
prodResult = 1
}
}
// take a LMC
for(let i = 0; i < pairs.length;i++)
{
let m = pairs[i][0];
let n = pairs[i][1];
let a = pairs[i][0];
let b = pairs[i][1];
let mmc = 0;
let r = 0
do
{
r = m%n;
m=n;
n=r;
} while (r != 0);
mmc = (a * b)/m
LMC.push(mmc)
}
for(let i = 0; i < product.length; i++){
result += product[i]-LMC[i]
}
return result
}
console.log(sumDifferencesBetweenProductsAndLCMs(pairs));
You can do all calculation in single loop only which will reduce your run time complexity.
let pairs = [[15,18], [4,5], [12,60]];
function sumDifferencesBetweenProductsAndLCMs (pairs) {
let result = 0;
// take a product
for(let i = 0; i < pairs.length;i++) {
let prodResult = 1;
for(let j = 0; j < pairs[i].length;j++) {
prodResult *= pairs[i][j]
}
const lcmResult = lcm(pairs[i][0], pairs[i][1]);
result += prodResult - lcmResult;
}
return result
}
function lcm(a, b) {
return (a / gcd(a, b)) * b;
}
function gcd(a, b) {
if (a === 0) {
return b;
}
return gcd(b % a, a);
}
console.log(sumDifferencesBetweenProductsAndLCMs(pairs));
.as-console-wrapper {
top: 0;
}
I am following the Nature of Code tutorial by Code Train and when I tested the code I got the TypeError. It pointed to function FromArray, line 19. I am trying to follow his coding challenge on teaching the neural network xor, where he visualizes the xor problem. The code I have so far should produce a flicking black and white screen. Here is a specific error message I got:
at Function.fromArray (matrix.js:19)
at NeuralNetwork.train (nn.js:61)
at draw (sketch.js:44)
at e.d.redraw (p5.min.js:33)
at e.<anonymous> (p5.min.js:32)
at e.<anonymous> (p5.min.js:32)
at new e (p5.min.js:32)
at e (p5.min.js:32).
I tried rewatching some of the videos to see if I missed something and I even checked with his code on GitHub but I still get that error. I tried searching for what to do with TypeError but most answers I found on forums.
Please help. Also, his tutorial series is really good.
//This is my code for the matrix math (Matrix.js):
// let m = new Matrix(3,2);
class Matrix {
constructor(rows, cols) {
this.rows = rows;
this.cols = cols;
this.data = [];
for (let i = 0; i < this.rows; i++) {
this.data[i] = [];
for (let j = 0; j < this.cols; j++) {
this.data[i][j] = 0;
}
}
}
static fromArray(arr) {
let m = new Matrix(arr.length, 1);
for (let i = 0; i < arr.length; i++) {
m.data[i][0] = arr[i];
}
return m;
}
static subtract(a, b) {
// Return a new Matrix a-b
let result = new Matrix(a.rows, a.cols);
for (let i = 0; i < result.rows; i++) {
for (let j = 0; j < result.cols; j++) {
result.data[i][j] = a.data[i][j] - b.data[i][j];
}
}
return result;
}
toArray() {
let arr = [];
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
arr.push(this.data[i][j]);
}
}
return arr;
}
randomize() {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.data[i][j] = Math.random() * 2 - 1;
}
}
}
add(n) {
if (n instanceof Matrix) {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.data[i][j] += n.data[i][j];
}
}
} else {
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.data[i][j] += n;
}
}
}
}
static transpose(matrix) {
let result = new Matrix(matrix.cols, matrix.rows);
for (let i = 0; i < matrix.rows; i++) {
for (let j = 0; j < matrix.cols; j++) {
result.data[j][i] = matrix.data[i][j];
}
}
return result;
}
static multiply(a, b) {
// Matrix product
if (a.cols !== b.rows) {
console.log('Columns of A must match rows of B.')
return undefined;
}
let result = new Matrix(a.rows, b.cols);
for (let i = 0; i < result.rows; i++) {
for (let j = 0; j < result.cols; j++) {
// Dot product of values in col
let sum = 0;
for (let k = 0; k < a.cols; k++) {
sum += a.data[i][k] * b.data[k][j];
}
result.data[i][j] = sum;
}
}
return result;
}
multiply(n) {
if (n instanceof Matrix) {
// hadamard product
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.data[i][j] *= n.data[i][j];
}
}
} else {
// Scalar product
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
this.data[i][j] *= n;
}
}
}
}
map(func) {
// Apply a function to every element of matrix
for (let i = 0; i < this.rows; i++) {
for (let j = 0; j < this.cols; j++) {
let val = this.data[i][j];
this.data[i][j] = func(val);
}
}
}
static map(matrix, func) {
let result = new Matrix(matrix.rows, matrix.cols);
// Apply a function to every element of matrix
for (let i = 0; i < matrix.rows; i++) {
for (let j = 0; j < matrix.cols; j++) {
let val = matrix.data[i][j];
result.data[i][j] = func(val);
}
}
return result;
}
print() {
console.table(this.data);
}
}
if (typeof module !== 'undefined') {
module.exports = Matrix;
}
//This the code that trains the neural network:
function sigmoid(x) {
return 1 / (1 + Math.exp(-x));
}
function dsigmoid(y) {
// return sigmoid(x) * (1 - sigmoid(x));
return y * (1 - y);
}
class NeuralNetwork {
constructor(input_nodes, hidden_nodes, output_nodes) {
this.input_nodes = input_nodes;
this.hidden_nodes = hidden_nodes;
this.output_nodes = output_nodes;
this.weights_ih = new Matrix(this.hidden_nodes, this.input_nodes);
this.weights_ho = new Matrix(this.output_nodes, this.hidden_nodes);
this.weights_ih.randomize();
this.weights_ho.randomize();
this.bias_h = new Matrix(this.hidden_nodes, 1);
this.bias_o = new Matrix(this.output_nodes, 1);
this.bias_h.randomize();
this.bias_o.randomize();
this.learning_rate = 0.1;
}
feedforward(input_array) {
// Generating the Hidden Outputs
let inputs = Matrix.fromArray(input_array);
let hidden = Matrix.multiply(this.weights_ih, inputs);
hidden.add(this.bias_h);
// activation function!
hidden.map(sigmoid);
// Generating the output's output!
let output = Matrix.multiply(this.weights_ho, hidden);
output.add(this.bias_o);
output.map(sigmoid);
// Sending back to the caller!
return output.toArray();
}
train(input_array, target_array) {
// Generating the Hidden Outputs
let inputs = Matrix.fromArray(input_array);
let hidden = Matrix.multiply(this.weights_ih, inputs);
hidden.add(this.bias_h);
// activation function!
hidden.map(sigmoid);
// Generating the output's output!
let outputs = Matrix.multiply(this.weights_ho, hidden);
outputs.add(this.bias_o);
outputs.map(sigmoid);
// Convert array to matrix object
let targets = Matrix.fromArray(target_array);
// Calculate the error
// ERROR = TARGETS - OUTPUTS
let output_errors = Matrix.subtract(targets, outputs);
// let gradient = outputs * (1 - outputs);
// Calculate gradient
let gradients = Matrix.map(outputs, dsigmoid);
gradients.multiply(output_errors);
gradients.multiply(this.learning_rate);
// Calculate deltas
let hidden_T = Matrix.transpose(hidden);
let weight_ho_deltas = Matrix.multiply(gradients, hidden_T);
// Adjust the weights by deltas
this.weights_ho.add(weight_ho_deltas);
// Adjust the bias by its deltas (which is just the gradients)
this.bias_o.add(gradients);
// Calculate the hidden layer errors
let who_t = Matrix.transpose(this.weights_ho);
let hidden_errors = Matrix.multiply(who_t, output_errors);
// Calculate hidden gradient
let hidden_gradient = Matrix.map(hidden, dsigmoid);
hidden_gradient.multiply(hidden_errors);
hidden_gradient.multiply(this.learning_rate);
// Calcuate input->hidden deltas
let inputs_T = Matrix.transpose(inputs);
let weight_ih_deltas = Matrix.multiply(hidden_gradient, inputs_T);
this.weights_ih.add(weight_ih_deltas);
// Adjust the bias by its deltas (which is just the gradients)
this.bias_h.add(hidden_gradient);
// outputs.print();
// targets.print();
// error.print();
}
}
//And this does the sketch and outputs the results:
let nn;
//Test Data
let training_data = [
{
inputs: [0,1],
targets: [1]
},
{
inputs: [1,0],
targets: [1]
},
{
inputs: [0,0],
targets: [0]
},
{
inputs: [1,1],
targets: [0]
},
];
function setup() {
//Test Data
// for (let i = 0; i < 50000; i++) {
// let data = random(training_data);
// nn.train(data.inputs, data.targets);
// }
// console.log(nn.feedforward([1,0]));
// console.log(nn.feedforward([0,1]));
// console.log(nn.feedforward([1,1]));
// console.log(nn.feedforward([0,0]));
createCanvas(400, 400);
nn = new NeuralNetwork(2, 2, 1);
}
function draw() {
background(0)
for (let i = 0; i < 1000; i++) {
let data = random(training_data);
nn.train(data.inputs, data.outputs);
}
let resolution = 10;
let cols = width / resolution;
let rows = height / resolution;
for (let i = 0; i < cols; i++) {
for (let j = 0; j < rows; j++) {
fill(random(255));
rect(i*resolution,j*resolution,resolution, resolution)
}
}
}
For example is there a performance difference between these two snippets:
var my_array = [''];
for (var i = 0; i < 2000; i++) {
my_array[0] += i;
}
and
var my_array = [''];
var my_string = array[0];
for (var i = 0; i < 2000; i++) {
my_string += i;
}
Thanks !
See for yourself (lower is better).
var suite = [
function test0() {
var t0, t1;
t0 = performance.now();
var my_array = [''];
for (var i = 0; i < 2000; i++) {
my_array[0] += i;
}
t1 = performance.now();
return t1 - t0;
},
function test1() {
var t0, t1;
t0 = performance.now();
var my_array = [''];
var string = my_array[0];
for (var i = 0; i < 2000; i++) {
string += i;
}
my_array[0] = string;
t1 = performance.now();
return t1 - t0;
}];
var tests = [0, 0];
var amount = [1000, 1000];
function run(test) {
if (amount[test]-- > 0 && test < 2) {
tests[test] += suite[test]();
setTimeout(function(){run(test)}, 0);
} else if (test < 1) {
document.write('<pre>Running test 1 in 1 second</pre>');
setTimeout(function(){
document.write('<pre>Running test 1</pre>');
run(test+1)
}, 1000);
} else {
document.write('<pre>1000 runs complete</pre>');
document.write('<pre>Test 0 total: ' + tests[0] + 'ms</pre>');
document.write('<pre>Test 1 total: ' + tests[1] + 'ms</pre>');
}
}
setTimeout(function(){
document.write('<pre>Running test 0</pre>');
run(0);
}, 1000);
I have the following code in my index.html page
<body>
<script type="text/javascript" src="words.js"></script>
<script>
var words = [];
window.onload = function () {
words = getwords();
};
</script>
</body>
And in word.js file
function getwords() {
var block = [];
var keyword = ['HELLO', 'CYCLE', 'APPLE', 'albatross', 'platform', 'OPERA', 'COURT', 'HOUSE', 'NEWEST', 'AEROPLANE', 'SCIENTIST', 'CORRIDOR', 'BUTTERFLY'.
'MUSICAL', ' AUSTRALIA', 'XYLOPHONE', 'TAPESTRY', 'DREAM', 'NEEDLE', 'GIRAFFE'
];
var index = [];
for (var p = 0; p < keyword.length; p++) {
index[p] = 0;
}
for (var i = 0; i < 8; i++) {
var x = Math.floor(Math.random() * (keyword.length - 1));
for (var j = 0; j <= i; j++) {
if ((words[j] !== keyword[x]) && (index[x] !== 1)) {
block[i] = keyword[x];
index[x] = 1;
}
}
}
return block;
}
I want my getwords function to return any 8 words from keyword array everytime it is called in the onload and it should get stored in words array and those words shouldnt be repaeted next time. However my code doesn't work. May I know my mistake? Please help!
I tried
function getwords(){
var block = [], index =[];
var rem = keyword.length -1;
for(var p=0 ;p <(rem+1) ;p++)
{
index[p]=0;
}
for(var i = 0; i < rem; ++i) keys.push(i);
for(var i=0; i<8 ;i++) {
var x = Math.floor(Math.random() * rem);
while(index[x]===1)
{
x = parseInt(Math.random() * rem);
}
block.push(keyword[x]);
index[x]=1;
}
return block;
}
Still gives some same words on second call.
A small mistake has cost you this problem ...
While storing the indexes in the index array you are using index[p] = 0;
But which should be
for(var p = 0; p < keyword.length; p++) {
index[p] = p;
}
here is the Working Example
I can give you a nicer approach. Tested to be OK, have a try.
var keyword=[
'HELLO', 'CYCLE', 'APPLE', 'albatross', 'platform',
'OPERA', 'COURT', 'HOUSE', 'NEWEST', 'AEROPLANE',
'SCIENTIST', 'CORRIDOR', 'BUTTERFLY', 'MUSICAL',
'AUSTRALIA', 'XYLOPHONE', 'TAPESTRY', 'DREAM',
'NEEDLE', 'GIRAFFE'];
var keys = [];
for(var i = 0; i < keyword.length; ++i) keys.push(i);
function getwords(count){
var block = [];
// first.
// pick and remove [count] times. Becareful when keys goes empty.
while(count > 0 && keys.length > 0) {
var x = parseInt(Math.random() * keys.length);
block.push(keyword[keys[x]]);
keys[x] = keys[keys.length-1];
keys.pop();
--count;
}
return block;
}
console.log(getwords(8));
console.log(getwords(8));
console.log(getwords(8));
What you mean by "doesn't work"? What shows the console?
'BUTTERFLY'.'MUSICAL'. There's a dot instead of a comma.
Hope it helps.