Okay, so I followed a previous post on creating a hear rate monitor and tweaked it a bit to fit my web design. Instead of setting Var Data how would I randomize the numbers between 1 and 300 over and over again until it reaches 200 random numbers total and draws them? Thanks for your time. This is my code but I took out most of the Var Data as it's 200 numbers long!
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.fillStyle = "#dbbd7a";
ctx.fill();
var fps = 60;
var n = 1;
var data = [
110, 149, 89, 150, 117, 150, 143, 82, 12, 92, 144, 73, 82, 200,
177, 149, 199, 116, 88, 105, 123, 12, 82, 72, 66, 15, 177, 182,
199, 116, 159, 150, 100, 10, ];
drawWave();
function drawWave() {
setTimeout(function() {
requestAnimationFrame(drawWave);
ctx.lineWidth = "1";
ctx.strokeStyle = 'green';
n += 1;
if (n >= data.length) {
n = 1;
}
ctx.beginPath();
ctx.moveTo(n - 1, data[n - 1 ]);
ctx.lineTo(n, data[n]);
ctx.stroke();
ctx.clearRect(n+1, 0, 10, canvas.height);
}, 1000 / fps);
}
</script>
The essence would be something like this: an array of size 200, since you want 200 values, and using a loop randomly populate the values.
Math.random will generate a number between 0 (inclusive) and 1 (non-inclusive), multiplying by 300 will give you anything between 0 and 299.99... Math.floor() removes the decimal places (range becomes 0 and 299); so we add 1 in the end to get the 1 to 300 range you wanted.
Hope this helps
var data = [];
for(var i = 0; i < 200; ++i) {
data[i] = Math.floor(Math.random() * 300) + 1;
}
with an elegant one-liner:
var data = Array.apply(null, Array(200)).map(function(){
return Math.floor(Math.random() * 299) + 1;
});
the above will work with the sparse / falsy val els in the array.
One easy way to do this is the following:
// creating a new Array with a length of 20 (obviously
// adjust the '20' to '200' for your own use-case):
var arr = new Array(20);
// using Array.prototype.fill() to assign a value (an
// empty String) to each array element, in order that
// Array.prototype.forEach() can iterate over each array
// element:
arr.fill('').forEach(function(needle, i, haystack){
// the arguments are automagically available to the
// the anonymous function;
// needle: the current array-element of the Array,
// i: the index of the current array-element,
// haystack: the Array itself.
// here we set the array value using bracket notation:
haystack[i] = Math.floor(Math.random() * (300 - 1) + 1);
});
// outputting the array to the console:
console.log( arr );
var arr = new Array(20);
arr.fill('').forEach(function(needle, i, haystack) {
haystack[i] = Math.floor(Math.random() * (300 - 1) + 1);
});
// Setting the array as the text of the <body> element,
// given the lack of a Snippet console:
document.body.textContent = arr.join(', ') + '.';
JS Fiddle demo.
The portion of the posted solution that generates the random numbers within a range:
Math.floor(Math.random() * (300 - 1) + 1)
was effectively borrowed from an answer elsewhere on the site (https://stackoverflow.com/a/1527820/82548, written by Ionut G. Stan), and is explained in that answer.
However, briefly, it generates a random number between 0 and 1; multiplies that by 299 (300 - 1), so that the integer portion becomes a number between 0 and 299; and then 1 is added to ensure the integer is now between 1 and 300.
Afterwards we apply Math.float() to round that random number to the integer portion of the number. The answer I've linked to, above, explains it far more completely.
References:
JavaScript:
Array.
Array.prototype.fill().
Array.prototype.forEach().
Math.floor().
Math.random().
String.prototype.join().
Stack Overflow:
Generating random whole numbers in JavaScript in a specific range?
Related
I need to dynamically create array, knowing only how long I want it to be. So for example I need array to be 3 long so I need array = [-10, 0, 10], if I need array 9 long it will be [-40, -30, -20, -10, 0, 10, 20, 30, 40] etc. How can I do it automatically?
You can simply get the result using Array with fill
Since you only want 0 at the center that input should be odd.
const end = 9;
let start = Math.floor(end / 2);
const result = [
...Array(start).fill(0).map((_, i) => start * -10 + i * 10),
0,
...Array(start).fill(0).map((_, i) => (i + 1) * 10)
]
console.log(result)
Another solution with Array.from:
const createArray = (length) => Array.from({length}, (el, i) => Math.round(i - length / 2) * 10);
console.log(createArray(1))
console.log(createArray(3))
console.log(createArray(9))
Below is a 2D array that represents movement of an entity over a 2 second period:
[[10, 200, 0], [70, 170, 600], [110, 150, 1000], [155, 120, 1600], [155, 120, 2000]]
Each array elements contains x-coordinate, y-coordinate, and timestamp in such order.
I need to transform this data which shows location at sporadic moments in time to an array showing the location at a fixed rate of every 200ms. I need to interpolate the missing values.
I know the correct output is:
10 200 0
30 190 200
50 180 400
70 170 600
90 160 800
110 150 1000
125 140 1200
140 130 1400
155 120 1600
155 120 1800
155 120 2000
How can I achieve this?
FINAL EDIT HOPEFULLY
I think I understand the question now thanks to #j08691 and #ISAE
EDIT #Gershy pointed out that the 200ms step asked was hardcoded into my solution so I changed it to a variable.
Here is the NEW JSFiddle.
Here is the code:
const data = [
[10, 200, 0],
[70, 170, 600],
[110, 150, 1000],
[155, 120, 1600],
[155, 120, 2000]
];
const STEP = 200;
// log the starting position first
console.log("" + data[0][0] + " " + data[0][1] + " " + data[0][2] + "\n")
for (let i = 0; i < data.length - 1; i++) {
const array1 = data[i];
const array2 = data[i + 1];
//find how many updates you need to print for each comparison
const n = ((array2[2] - array1[2]) / STEP);
const xMovement = (array2[0] - array1[0]) / n;
const yMovement = (array2[1] - array1[1]) / n;
for (let j = 1; j <= n; j++) {
console.log("" + (array1[0] + xMovement * j) + " " +
(array1[1] + yMovement * j) + " " +
(array1[2] + STEP * j) + "\n");
}
}
EDIT
Ok I confused myself and others with this one a lot so I worked all of the way through it on JSFiddle.
I definitely works now.
___________
The problem just wants you to iterate through the 2D Array and log it to the console.
I don't want to do your homework for you but you'll need nested loops to iterate each and print. When you get to the end of an inner array, print a newline character as well. [this was rude...sry]
EDIT
Ok since someone downvoted me, here you go:
The iteration:
const data = [
[10, 200, 0],
[70, 170, 600],
[110, 150, 1000],
[155, 120, 1600],
[155, 120, 2000]
];
let n = 0
data.forEach(array => {
setTimeout(() => {
let line = ""
array.forEach(item => line += item + " ");
console.log(line + "\n");
}, n += 200);
})
The assessment is asking you to calculate the movement of elements for every 200ms period.
Taking the first and second elements for example, you have: [10, 200, 0], [70, 170, 600] which means that at the start (0ms) the element is in XY position of 10 & 200 respectively. after 600ms (2nd element) it is in XY position of 70 & 170. So the element has moved 60 X points (70 - 10) and -30 Y points (200 - 170).
You'll need to find the ms difference between each element and the next, find it's divisor to 200ms blocks, and calculate the position it should be at each 200ms.
To continue with the example, the difference between element 1 and 2 in ms (3rd number in the element) is 600ms which is 3 200ms blocks, so 60 X points divide to 3 (3 200ms steps) is 20. adding the start position of 10, you'll get 30, 50 and 70. -30 Y points divides into -10 movement in each 200ms timeframe, so it'll be 190, 180 and 170. And so on.
This is a matter of interpolation. We need to log the position every 200ms. Consider the 600th millisecond; it is very easy to log, because there is an entry for exactly the 600th millisecond - but the 800th millisecond is not as trivial, as it lands between the entries for 600ms and 1000ms. How do we log it? We take a weighted average of the two surrounding values. Note that this is called a "linear interpolation" (and is only one of several ways of filling in blanks in a dataset).
The following interpolate function allows any sequence to be interpolated using any timestep. The only restriction is that the data array must be sorted in ascending order by its millisecond value (already the case for your data).
let data = [
[10, 200, 0],
[70, 170, 600],
[110, 150, 1000],
[155, 120, 1600],
[155, 120, 2000]
];
let interpolate = (data, stepSize=200) => {
let result = [];
for (let ms = 0; true; ms += stepSize) {
// Find the two entries to either side of the current `ms`
// E.g. if current `ms` is 800, should return the 600ms and
// 1000ms entries. If `ms` is exactly equal to a particlar
// entry, `e1` and `e2` are *both* set to that entry.
// If we can't find both an entry before and after, return
// `null` for both entries.
let [ e1, e2 ] = (() => {
for (let i = 0; i < data.length; i++) {
// Can an exact match be found?
if (data[i][2] === ms)
return [ data[i], data[i] ];
// Do consecutive entries contain the current `ms`?
if (data[i + 1] && data[i][2] < ms && data[i + 1][2] > ms)
return [ data[i], data[i + 1] ];
}
return [ null, null ];
})();
// Stop once no more entries can be found
if (e1 === null) break;
// Get the distance between entries
let msDist = e2[2] - e1[2];
if (msDist === 0) {
// Handle an exact match by including the exact entry
result.push([ ...e1 ]);
} else {
// Handle moments between entries with an interpolated
// average:
// Get distance between `e1` and `ms`, and between `e2`
// and `ms`
let dist1 = ms - e1[2];
let dist2 = e2[2] - ms;
// Take the interpolated average. The bigger `dist2` is
// the more `e1` plays into the value. The bigger
// `dist1` is, the more `e2` plays into the value.
let mult1 = 1 - (dist1 / msDist);
let mult2 = 1 - (dist2 / msDist);
result.push([ e1[0] * mult1 + e2[0] * mult2, e1[1] * mult1 + e2[1] * mult2, ms ]);
}
}
return result;
};
// Do the interpolation
let interpolated = interpolate(data);
// Log the resulting items
console.log(interpolated.map(([ x, y, ms ]) =>
`${ms}ms: (${Math.round(x)}, ${Math.round(y)})`
));
I ported this function from a python answer to a similar question on this site. However, although the points are equidistant from each other, they are not centered on the line.
The first point is at 0 while the last is at 83 (the end of the line segment is 100).
How do I center this row of points?
Specifically, I want the first point to be the same distance from 0 that the last point is from 100.
'use strict';
function generatePoints(count, length) {
const points = []
for (let i = 0; i < count; i++) {
const a = i / count;
const x = a * length;
points.push(Math.round(x));
}
return points;
}
const points = generatePoints(6, 100);
console.log(points);
// [ 0, 17, 33, 50, 67, 83 ]
I tried this, but it doesn't appear to work as I expected:
for (let i = 0; i < points.length; i++) {
points[i] += (points[1] / 2);
points[i] = Math.round(points[i]);
}
console.log(points);
// [ 9, 26, 46, 63, 80, 96 ]
The first point is 9 away from 0, but the last point is 4 away from 100.
Change i / count to (i + 1) / (count + 1).
I have a large array of numbers that I need to distribute into x ranges of numbers, such that each range contains an equal number of elements from the original array.
For example, when x = 4 , the following array
[1, 1, 2.5, 3, 6, 7, 10, 11.2, 14, 25, 35, 50, 75, 85.5, 100, 120, 128.9, 150, 200, 260]
would produce an array of length x + 1 with the following
[1, 6.5, 30, 110, 260]
1 is the lowest value in the array
6.5 is the midpoint of 6 and 7
30 is the midpoint of 25 and 35
110 is the midpoint of 100 and 120
260 is the highest value
Essentially, this will give me 4 ranges of numbers 1-6.5, 6.5-30, 30-110, and 110-260. Each range would contain 5 numbers of the original array.
Needs to be able to handle a dynamic number of elements that will not necessarily be divided evenly by x.
I asked this question on Mathematics but was told it was more of a programming question.
Based on your question , the following javascript code should satisfy your requirements, I've tested its correctness with a few values of x, but you might want to check if this code applies to all possible test cases for your problem.
var arr = [1, 1, 2.5, 3, 6, 7, 10, 11.2, 14, 25, 35, 50, 75, 85.5, 100, 120, 128.9, 150, 200, 260, 261, 262, 263, 264, 265];
total_elem = arr.length;
var x = 5;
var each_set_elem = total_elem / x;
var i = 1;
var temp = [];
temp.push(arr[0]);
for (i = each_set_elem; i < total_elem; i += each_set_elem) {
this_elem = (arr[i] + arr[i - 1]) / 2;
temp.push(this_elem);
}
temp.push(arr[total_elem - 1]);
console.log(temp);
This code satisfies the test case in the question as well as for x=5 it spits out the correct 6 points so that the 5 ranges each have 4 elements from the given array set.
I have 10 sets of data coming in, and I need to set a radius for the first one to be the largest and then decrease by 10%.
my index comes in like: 1, 2, 3, 4, 5....
I am taking the index and dividing it by 1
var radiusTest = 1 / (index);
circleRadius = radiusTest * 100
Then I am multiplying it by 100, it is close to what I need but it does not degrade as nicely as I would like. Having each radius decrease by 10% is what I am looking for, not sure the best way of setting it up?
I think you are going for something like this:
var radiusTest = 1 - index * .1;
circleRadius = radiusTest * 100
So you have a value starting at 100% and decreasing in equal amounts over 10 iterations, or by 10%. Here is a way to implement this in JavaScript.
var steps = 10,
step,
stepSize = 1/steps,
radii = [];
for(step = 0; step <= steps; step++) {
radii[step] = (1-(stepSize * step)) * 100;
}
The array radii should contain:
[100, 90, 80, 70, 60, 50, 40,30,20, 10, 0]
You can mess with the constants to see different steps and step sizes.