simplify javascript array with loop syntax - javascript

I have a javascript array defined as below:
var hexgon = ['M',r*Math.cos(0/180*Math.PI),r*Math.sin(0/180*Math.PI)
,r*Math.cos(30/180*Math.PI),r*Math.sin(30/180*Math.PI)
,r*Math.cos(90/180*Math.PI),r*Math.sin(90/180*Math.PI)
,r*Math.cos(150/180*Math.PI),r*Math.sin(150/180*Math.PI)
,r*Math.cos(210/180*Math.PI),r*Math.sin(210/180*Math.PI)
,r*Math.cos(270/180*Math.PI),r*Math.sin(270/180*Math.PI),
,r*Math.cos(330/180*Math.PI),r*Math.sin(330/180*Math.PI),'Z']
How to use a loop to simplify this logic?

If you did not intend two commas in a row after the twelth element then this:
var hexgon = ['M', ...[0,30,90,150,210,270,330].flatMap(d => [r*Math.cos(d/180*Math.PI),r*Math.sin(d/180*Math.PI)]), 'Z']

If you can have a constant value as a step that gets added to Math.cos() and Math.sin() statements we might be able to do something.
Let's say we want to add 30 each time to the each array's element, we can do something like this: (Also noticed there are M and Z characters at the beginning and end of your array)
const newHexgon = new Array(16);
newHexgon[0] = 'M';
newHexgon[newHexgon.length - 1] = 'Z';
let counter = 0;
let step = 30;
for (let i = 1; i < newHexgon.length - 1; i += 2) {
newHexgon[i] = Math.cos(((counter * step) / 180) * Math.PI);
newHexgon[i + 1] = Math.sin(((counter * step) / 180) * Math.PI);
counter++;
}
console.log(newHexgon);
I created an array with a length of 16 and set the first and last elements to "M" and "Z" as in your array. Then I will loop every two elements at a time i += 2 and set the Math calculations and after finished in each iteration the counter gets added by one.

Related

create unique value and push to array in javascript

I need to create a array with unique values. In here if the created value is include in that array, then need to create another value and again need to check that newly created value exists in that array, if again exists then need to do the same check.
Here is the code I have tried, if I execute this, I think infinite looping scene happening.
let arr = [];
for(let i=0; i<10;i++) {
let k = 1;
let pass = (Math.floor(Math.random() * (10 - 6 + 1)) + 6)+'a';
while(k > 0){
k++;
if(arr.indexOf(pass) > -1) {
pass = (Math.floor(Math.random() * (10 - 6 + 1)) + 6)+'a';
} else {
arr.push(pass);
break;
}
console.log(arr)
}
}
What was the mistake in this code?
Yep, you're correct. It's an infinite loop.
The problem is the line pass = (Math.floor(Math.random() * (10 - 6 + 1)) + 6)+'a';. This will only ever generate one of 5 values. pass will only ever be
6a
7a
8a
9a
10a
Beause your array is 10 elements long, but you're only filling it with 5 possible elements, you will never be able to fill it with all unique elements. So it will go into an infinite loop trying to generate unique elements but never finding unique elements.
You need to rewrite the calculation of pass to generate more than 5 unique elements. Try pass = (Math.floor(Math.random() * 10))+'a'; and go from there.
let arr = [(Math.floor(Math.random() * (10)))+'a'];
for(let i=0; i<=10;i++) {
let k = 0;
let pass = (Math.floor(Math.random() * (10)))+'a';
while(k < arr.length){
k++;
if(arr.indexOf(pass) > -1){
pass = (Math.floor(Math.random() * (10 - 6 + 1)) + 6)+'a';
}else {
arr.push(pass);
break;
}
}
}
console.log(arr)
variable k is always > 0 in your condition and it loops infinitely.
edit 1:
answer updated based on #Mathew answer

Pure Javascript, Cannot assign variables to an array

I am still learning JS (not jquery). So in learning, I am starting with a simple game. I found a problem. I cannot get these arrays to work, as they are producing a NaN.
var clickMultiplier = 1.11;
var idleMultiplier = 1.15;
var idleBuffsCost = [];
idleBuffsCost[0] = 100;
var clickBuffsCost = [];
clickBuffsCost[0] = 100;
var trainerBuffsCost = [];
trainerBuffsCost[0] = 1250;
for (i = 1; i <= 20; i++) {
var j = i - 1;
idleBuffsCost[i] += idleBuffsCost[j] * idleMultiplier;
clickBuffsCost[i] = clickBuffsCost[i] + clickBuffsCost[j] * clickMultiplier;
trainerBuffsCost[i] += trainerBuffsCost[j] * 1.25;
}
console.log(clickBuffsCost[0]); // works = 100
console.log(clickBuffsCost[1]); // does not work NaN
What am I doing wrong?
Also, I am used to doing arrays (like the above) as
... idleBuffsCost[i-1]
However, that does not seem to be working.
What do you think? Am I not seeing the forest for the trees (I normally program in php/mysql/pascal/qb64(and other derivations) and a few more languages - just adding JS to the list hahaha)
ps the different assignments are because I was trying different logic operations.
thanks to a few people here - I made a simple mistake. the loop was trying to assign a value to an index that was not assigned yet. Here is the fix - I removed the += and left just =
idleBuffsCost[i] = idleBuffsCost[j] * idleMultiplier;
clickBuffsCost[i] = clickBuffsCost[j] * clickMultiplier;
trainerBuffsCost[i] = trainerBuffsCost[j] * 1.25;
special thanks to: #certainPeformance, #Wais Kamal and #David I wish I could green check them all. But they were helpful none-the-less, Thanks guys!
There is a little mistake in your code. Search this line of code.
clickBuffsCost[i] = clickBuffsCost[i] + (clickBuffsCost[j] * clickMultiplier);
change to:
clickBuffsCost[i] = clickBuffsCost[j] + (clickBuffsCost[j] * clickMultiplier); // notice the difference after the = part
Since i will start at 1, clickBuffsCost[1] is undefined because clickBuffsCost only consists of one item at the beginning.
Here is where you've gone wrong:
for (i = 1; i <= 20; i++) {
var j = i - 1;
idleBuffsCost[i] += idleBuffsCost[j] * idleMultiplier;
clickBuffsCost[i] = clickBuffsCost[i] + (clickBuffsCost[j] * clickMultiplier);
trainerBuffsCost[i] += trainerBuffsCost[j] * 1.25;
}
First of all, define i before using it. Defining variables is good programming practice.
clickBuffsCost[i] = clickBuffsCost[i] + (clickBuffsCost[j] * clickMultiplier);
In the first iteration of your loop, i has the value 1, while j has the value 0. You are setting the second element of clickBuffsCost as clickBuffsCost[i] + (clickBuffsCost[j] * clickMultiplier). clickBuffsCost[i] (which is equal to clickBuffsCost[1] in this case) is undefined, which is why you are getting NaN when calling console.log(clickBuffsCost[0]).
You need to initialise your array lengths. For example, if you know you have 20 elements in an array, you should initialise an array as follows:
const testArr = new Array(20);.
Alternatively, if you don't know the length of your array, instead of indexing the ith element of the array and assigning it a value, you could use the array push(..) function. This method means you do not have to initialise an array with a length.
You can read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array

Reducing a number on each iteration until it reaches exactly 0

I want to reduce n to 0 on the last iteration but my calculations are wrong. Im overlooking something. Right now im doing Math.round(n / loops). I need to find a way to disperse the substraction in such a way so that in the last iteration n becomes 0 while the range between each n´s is constant.
function check(a, b) {
let loops = a / b;
let n = 200;
for (let i = 0; i <= loops; i++) {
console.log(n);
n -= Math.round(200 / loops);
}
}
check(60, 10)
Edit: Im sorry but these downvotes are ridiculous.
The main problem with your code is that the expression n / loop is different in each iteration. You might have intended that this expression was constant, in which case the logic would have been more reasonable.
Use a separate variable that starts with the value of n and then is the subject of the subtractions, but without changing the original value of n that is used in the expression n / loop:
function check(a, b) {
let loops = a / b;
let n = 200; // don't change n after this.
let n2 = n; // use a separate variable for that.
for (let i = 0; i <= loops; i++) {
console.log(Math.round(n2)); // only round in output
n2 -= n / loops; // use n, but only change n2
}
}
check(60,10);

d3 how to turn a set of numbers into a larger set representative of the first set

Say I have array [1,2,5,18,17,8] and I want to turn that into an array of length 40 that follows the same path.
a = [1,2,5,18,17,8];
stepSize = 1 / (40 / a.length);
then i think i could do something like
steps = [];
for( var i = 0; i < 1; i+= stepSize) {
steps.push(d3.interpolate(a[0],a[1])(i));
}
and then repeat that for all the elements. My question is there a better way to do this?
I can only guess what your real problem is but I think you want to plot these values and have a smooth curve. In that case use line.interpolate() https://github.com/mbostock/d3/wiki/SVG-Shapes#line_interpolate
In case you DO know what you need and your solution works for you, take this tip:
Never iterate over stepSize. Calculate it once and multiply it with i in every loop where i goes from 0 to 40. This way you work around precision problems.
Your algorithm cleaned up, tested and working:
var a = [1,5,12,76,1,2];
var steps = 24;
var ss = (a.length-1) / (steps-1);
var result = new Array(steps);
for (var i=0; i<steps; i++) {
var progress = ss * i;
var left = Math.floor(progress);
var right = Math.ceil(progress);
var factor = progress - left;
result[i] = (1 - factor) * a[left] + (factor) * a[right];
// alternative that actually works the same:
//result[i] = d3.interpolateNumber(a[left], a[right], factor);
}
console.log(result);

javascript - generate a new random number

I have a variable that has a number between 1-3.
I need to randomly generate a new number between 1-3 but it must not be the same as the last one.
It happens in a loop hundreds of times.
What is the most efficient way of doing this?
May the powers of modular arithmetic help you!!
This function does what you want using the modulo operator:
/**
* generate(1) will produce 2 or 3 with probablity .5
* generate(2) will produce 1 or 3 with probablity .5
* ... you get the idea.
*/
function generate(nb) {
rnd = Math.round(Math.random())
return 1 + (nb + rnd) % 3
}
if you want to avoid a function call, you can inline the code.
Here is a jsFiddle that solves your problem : http://jsfiddle.net/AsMWG/
I've created an array containing 1,2,3 and first I select any number and swap it with the last element. Then I only pick elements from position 0 and 1, and swap them with last element.
var x = 1; // or 2 or 3
// this generates a new x out of [1,2,3] which is != x
x = (Math.floor(2*Math.random())+x) % 3 + 1;
You can randomly generate numbers with the random number generator built in to javascript. You need to use Math.random().
If you're push()-ing into an array, you can always check if the previously inserted one is the same number, thus you regenerate the number. Here is an example:
var randomArr = [];
var count = 100;
var max = 3;
var min = 1;
while (randomArr.length < count) {
var r = Math.floor(Math.random() * (max - min) + min);
if (randomArr.length == 0) {
// start condition
randomArr.push(r);
} else if (randomArr[randomArr.length-1] !== r) {
// if the previous value is not the same
// then push that value into the array
randomArr.push(r);
}
}
As Widor commented generating such a number is equivalent to generating a number with probability 0.5. So you can try something like this (not tested):
var x; /* your starting number: 1,2 or 3 */
var y = Math.round(Math.random()); /* generates 0 or 1 */
var i = 0;
var res = i+1;
while (i < y) {
res = i+1;
i++;
if (i+1 == x) i++;
}
The code is tested and it does for what you are after.
var RandomNumber = {
lastSelected: 0,
generate: function() {
var random = Math.floor(Math.random()*3)+1;
if(random == this.lastSelected) {
generateNumber();
}
else {
this.lastSelected = random;
return random;
}
}
}
RandomNumber.generate();

Categories

Resources