Connecting data from 2 arrays - javascript

I have a little bit hard question, but I try to explain it:
So, I have 2 arrays. First array - array of cities. The second is the matrix with distances between this cities;
var cities = ['Gamburg', 'Dresden', 'Berlin', 'Bayern', 'Dortmund'];
var distanceMatrix = [
[0, 131, 523, 251, 600],
[131, 0, 785, 123, 541],
[252, 785, 0, 241, 741],
[251, 123, 241, 0, 632],
[600, 541, 741, 632, 0]
];
I need to generate a train with randomly choosen department and arrival point, with is not a problem. The problem is how to connect this 2 points with distance matrix correctly. If its possible. For example: distance between cities[1] and cities[3] accords to distanceMatrix[1][3] etc. So I need a function which randomly pick 2 towns and show distance between them according to distanceMatrix.
P.S. 2 days of hard mind work, and all I've done - is just 5 switch() functions, which is wrong way to complete this task.
Thank you !

You could take Array#indexOf for getting the index as accessor for the matrix.
var cities = ['Gamburg', 'Dresden', 'Berlin', 'Bayern', 'Dortmund'],
distances = [[0, 131, 523, 251, 600], [131, 0, 785, 123, 541], [252, 785, 0, 241, 741], [251, 123, 241, 0, 632], [600, 541, 741, 632, 0]];
function getDistance(city1, city2) {
return distances[cities.indexOf(city1)][cities.indexOf(city2)];
}
console.log(getDistance('Dresden', 'Berlin'));
console.log(getDistance('Dortmund', 'Bayern'));
An advanced solution could use an object with the indices.
var cities = ['Gamburg', 'Dresden', 'Berlin', 'Bayern', 'Dortmund'],
indices = { Gamburg: 0, Dresden: 1, Berlin: 2, Bayern: 3, Dortmund: 4 },
distances = [[0, 131, 523, 251, 600], [131, 0, 785, 123, 541], [252, 785, 0, 241, 741], [251, 123, 241, 0, 632], [600, 541, 741, 632, 0]];
function getDistance(city1, city2) {
return distances[indices[city1]][indices[city2]];
}
console.log(getDistance('Dresden', 'Berlin'));
console.log(getDistance('Dortmund', 'Bayern'));

Well, if I understood the problem correctly, you look for a way to form and access the matrix.
Let's first see the problem as indexes.
var cities = ['Gamburg', 'Dresden', 'Berlin', 'Bayern', 'Dortmund'];
cities[0] = Gamburg, cities[1] = Dresden, and so on.
The question is how to pick to cities at random and return the distance between the two.
function randomCities() {
while(true)
{
//Let's generate a random number between 0 and 4.
var randomCity_A = Math.floor((Math.random() * 4) + 0);
var randomCity_B = Math.floor((Math.random() * 4) + 0);
// add a condition that cities are not the same
if ( randomCity_A != randomCity_B){
var distance = distanceMatrix[randomCity_A][randomCity_B];
return "Distance between " + cities[randomCity_A] +" and " +
cities[randomCity_A] +": "+distance;
}
}
}
console.log(randomCities());
console.log(randomCities());

Related

Round off number to the nearest Highest number from array besides last one

var counts = [2, 33, 61, 92, 125, 153, 184, 215, 245, 278, 306, 335, 365],
goal = 35;
let min = Math.min(...counts.filter(num => num >= goal));
console.log(min)
This works but in case goal=400, I will get 365 back as it's the last number in the array
You could find the wanted value or take the value at last index.
const
find = (array, value) => array.find((v, i, { length }) =>
v >= value || i + 1 === length
),
counts = [2, 33, 61, 92, 125, 153, 184, 215, 245, 278, 306, 335, 365];
console.log(find(counts, 35));
console.log(find(counts, 400));
A slightly different approach by taking the last item, if undefined.
const
find = (array, value) => array.find(v => v >= value) ?? array.at(-1),
counts = [2, 33, 61, 92, 125, 153, 184, 215, 245, 278, 306, 335, 365];
console.log(find(counts, 35));
console.log(find(counts, 400));
This will give you the smallest number above the goal, or the largest number in counts if there are no numbers above the goal
const counts = [2,33,61,92,125,153,184,215,245,278,306,335,365]
goal = 35;
const above_goal = counts.filter(num => num >= goal)
const min = above_goal.length === 0 ? Math.max(counts) : Math.min(above__goal)
console.log(min)

I try to use three.js to calculate the point after rotate and translate but the result is wrong?

I want to calculate the point A to H after rotate 90 degrees and rotate to direction vector CE(-42,51,11) and let the point translate to point(-62,283,63) and reduce (66/151).like this then point A will be(-62, 283,63), point B will be(-104,334,74)
But the result point B is not the correct answer.
I've tried multiple variations of this, but none of them seem to work.Thank you in advance and please excause my bad english. Best regards.
const tree = [
[ 0, 0, 0], // A
[ 2, 151, 2], // B
[ -62, 283, 63], // C
[ 62, 296, -58], // D
[-104, 334, 74], // E
[ -58, 338, 45], // F
[ 67, 403, -55], // G
[ 105, 365, -86], // H
]
let axis = new THREE.Vector3(-42, 51, 11)
// Normalize the axis:
axis.normalize()
// Define the matrix:
let matrix = new THREE.Matrix4()
// Define the rotation in radians:
let radians = 90 * Math.PI / 180
// Rotate the matrix:
matrix.makeRotationAxis(axis, radians)
let newTree = []
for(const vector of tree) {
// Define the vector3:
let vec = new THREE.Vector3(vector[0], vector[1], vector[2])
vec.applyMatrix4(matrix)
vec.multiplyScalar(66/151);//reduce
let transVector = new THREE.Vector3( -62, 283, 63);//translate
vec.add(transVector)
newTree.push(vec.toArray())
}
console.log(newTree)

Create dynamic array within certain range values

I am trying to find the best way to generate an array that has the following output:
[135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 275, 276, 277 , 278, 279, 280, 281, 282, 283, 284, 285, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 555, 556, 557, 558, 559, 560, 561, 562, 563, 564, 565, 675, 676, 677, 678, 679, 700, 701, 702, 703, 704, 705 ...
As you can see it has a set of limits from 140 - 280 - 420 - 560 - 700 ( adds 148 to each value)
and then there's an interval with minus 5 and plus 5 for each value.
I already tried this approach
scrollFrom = Array.from(Array(bytesIndexTo).keys()).map(i => 140 + i * 140);
That returns me:
[140, 280, 420, 560, 700, ...
However I also need the plus and minus 5 values intervals...
I also noticed it uses to much resources.
const prev = [
[135,136,137,138,139],
[275,276,277,278,279],
];
const after = [
[141,142,143,144,145],
[281,282,283,284,285],
];
for (let i = 0; i < scrollFrom.length; i++) {
scrollFrom.push( scrollFrom[i] );
}
The purpose of this array is to have a set of values that will help me to identify a certain scroll position in order to execute a function, the addition of this intervals will help me to figure the scroll position even if the user scrolls fast.
Maybe I could load the values inside a .json and load them ?
What do you think ? thanks in advance
Once you create an array of central values (eg [140, 280, 420, 560, 700]), you can use flatMap to iterate over each item and construct another array of the 5 values below and above it:
const bytesIndexTo = 4;
const result = Array.from(
{ length: bytesIndexTo },
(_, i) => (i + 1) * 140
)
.flatMap(num => Array.from(
{ length: 11 },
(_, j) => num - 5 + j
));
console.log(result);
So, if you all you really want to do is to be able to test if a number is within 5 of a sentinel multiple, then I don't think you really want to be generating a giant array and using .includes(). That would be slow. If you were going to pre-generate values, you should use a Set and then use .has() which should be a lot faster than .includes() for a large set of data.
But, it seems to be that you can just calculate a lot faster without doing any pre-generation at all.
In the code below, we divide by the multiple (140) and then look at the remainder. If the remainder is <=5 or >= 135, then it's within 5 of the multiple, otherwise not. It's really that simple. Since it appears you don't want the numbers 0-5 (around the zero multiple) to be counted as true, we add a special case for those.
// tests to see if a value is within 5 of a multiple of 140
const multiple = 140;
const over = 5;
const below = multiple - over;
function testValue(val) {
if (val < below) return false;
const delta = val % multiple; // divide by multiple, get remainder
return (delta <= over || delta >= below); // see if remainder in right range
}
// run some tests on numbers at edges of the interval ranges
[
0, 1,
134, 135, 140, 144, 145, 146, // around 140
274, 275, 280, 284, 285, 286, // around 280
414, 415, 420, 424, 425, 426, // around 420
554, 555, 560, 564, 565, 566 // around 560
].forEach(num => {
console.log(`${num}: ${testValue(num)}`);
});

Flatten curve of array of numbers

I'm trying to find the technique of Normalising (not sure if that is the right word) a range of numbers.
Say I have an array:
[0, 1, 2, 3, 4, 70, 80, 900]
I want to flatten or average out the range curve, so it's more like:
[10, 11, 12, 13, 14, 50, 100, 300]. // not a real calculation
So increasing the smaller numbers in relation to reducing the larger numbers.
What is this technique called? Normalised scale? I wish to implement this in some Javascript.
UPDATE: Here is hopefully a better description of what I'm trying to do:
I have an original array of numbers:
[0, 10, 15, 50, 70, 100]
When processed through a function averageOutAllNumbers(array, slider) will produce and array that when slider is set to 100% looks like:
[0, 20, 40, 60, 80, 100] // the curve has been flattened
when slider is set to 0%, it will return the original array. If slider is set to 50%, the returned array will look something like:
[0, 12, 19, 52, 88, 100] // the curve is less steep [do not take these number literally, I'm guess what the output would be based on the slider].
the array.max() will alway be 100.
Thanks for the comments so far, they did point me closer to the solution.
No thanks to the trolls who down-voted; if you can't fix it no one can—right!
When I updated my question I realised that "increasing the smaller numbers in relation to reducing the larger numbers" would eventually lead to an evenly distributed set of numbers, e.g. [20, 20, 20, 20, 20]. However I did actually want something like I stated in the question: [0, 20, 40, 60, 80, 100] // the curve has been flattened. I did some more searching for things like:
Evenly space an array of oddly spaced numbers
Making a list of evenly spaced numbers in a certain range
Return evenly spaced numbers over a specified interval
Find what percent X is between two numbers
Amongst the list of search result I saw the answer to my original question: "What is this technique called?" Linear Interpolation
Based on that I was able to create the following:
var orig = [3, 11, 54, 72, 100];
function lerp(n, x0, x1) {
// returns a position: x that is n percent between y0 and y1
// As numbers in array are x only, y values are fixed to 0(start) - 1(end)
const y0 = 0;
const y1 = 1;
const x = ((y1 - n)*x0 + (n - y0)*x1) / (y1 - y0);
return x;
}
var flattenedEven = orig.map((value, index, arr) => {
return lerp(1, value, (Math.max(...arr)/arr.length) * (index + 1));
});
//=> [20, 40, 60, 80, 100]
var flattenedCurve = orig.map((value, index, arr) => {
return lerp(.7, value, (Math.max(...arr)/arr.length) * (index + 1));
});
//=> [14.9, 31.3, 58.2, 77.6, 100]

How do I use this color object?

I do have an array of objects (book) here. My question is: How do I use the "color" object so each book has its color property? I think it has to be something like this -> book[amount].color <- but I can't make it work.
I don't know how to call the color property.
This is the array of objects:
var book = [
{title: "The Giver",
stars: 3,
author: "Lowry Loys",
color: color(0, 38, 255), //How do I make this property work in the code?
image: true},
{title: "How to win friends",
stars: 5,
author: "Dale Carnegie",
color: color(214, 255, 219),
image: false},
{title: "Principios fund. de la filosofía",
stars: 5,
author: "Georges Politzer",
color: color(115, 0, 255),
image: false}
];
This is the code
// draw shelf
fill(173, 117, 33);
rect(0, 120, width, 10);
// draw books + title + author
for (var amount = 0; amount < book.length; amount++) { //draw books
fill(214, 255, 219);
rect(154*amount, 20, 90, 100);
fill(0, 0, 0);
textSize(13);
text(book[amount].title, 5 + 158*amount, 27, 68, 100); //draw title
textSize(10);
text(book[amount].author, 5 + 155*amount, 91, 75, 100); //draw author
for (var s = 0; s < book[amount].stars; s++) { //draw stars
image(getImage("cute/Star"), 11 + s * 15 + amount * 151, 98, 15, 22);
}
for (var i = 0; i < book[amount].image; i++) { //draw stars
image(getImage("avatars/aqualine-sapling"), 9 + i * 60 + amount * 46, 42, 36, 39);
}
}
Assuming you don't have a color function, you'll have to quote those properties and then extract the color information.
In this simple example a regex grabs the color values from the (index 1) object, and then sets the background color of a temporary element.
var book=[{title:"The Giver",stars:3,author:"Lowry Loys",color:'color(0, 38, 255)',image:!0},{title:"How to win friends",stars:5,author:"Dale Carnegie",color:'color(214, 255, 219)',image:!1},{title:"Principios fund. de la filosofía",stars:5,author:"Georges Politzer",color:'color(115, 0, 255)',image:!1}]
const result = document.getElementById('result');
const color = book[1].color.match(/(\d+)/g);
result.style.backgroundColor = getColor(color);
function getColor(color) {
return `rgb(${color[0]}, ${color[1]}, ${color[2]})`;
}
<div id="result">sdfdsfdsf</div>
The color function doesn't exist in plain javascript. I think the easiest way will be to store your colors as a HEXs in strings like below:
var book = [{
title: "The Giver",
stars: 3,
author: "Lowry Loys",
color: "#0026ff", // converted rgb(0, 38, 255)
image: true
}];
book[0].color; // "#0026ff"
You can use e.g. this tool to manually convert colors to HEX. If you don't like it just implement your own color function to convert rgb to hex (link).
Here you can also find an interesting npm package named Qix-/color:
JavaScript library for immutable color conversion and manipulation with support for CSS color strings.
Hope it helps!

Categories

Resources