How to remove mathematically cancelling values from array of numbers? - javascript

My application is collecting a series of adjustments to budget values to try to reach a goal. So far, I'm collecting the adjustments into an array and totaling their values to show how much more needs to be cut to reach the goal:
const goal = 25;
let cutTotal = 0;
let remaining = 0;
let cuts = [];
function update (value) {
// Values are numbers: -1, 1, 0.1, -0.1. This function gets called
// when any update is made to a budget value.
cuts.push(value);
cutTotal = 0;
cuts.forEach(function (value) {
cutTotal += value;
});
remaining = goal - cutTotal;
}
This is working as expected, but I'm thinking there has to be a reasonably performant way to manage the length of the cuts array by removing values that are redundant. (Adding and subtracting 1 from the total doesn't change the total, so why store the values?)

Related

Stopwatch Lap Comparison

I have created a stopwatch web app with HTML, CSS, and Vanilla JS. It counts and stops just fine, with a lap function that prints a separate lap timer running under the main timer.
Now, my issue comes up when I'm trying to get the highest and lowest lap times. I am able to get those values to a certain degree but it's not completely accurate in some time cases. For instance, when you lap 00:02:03 and 00:00:42 respectively, my code picks the first time as the lowest lap time because '03 is lower than '42. The same situation happens when selecting the highest lap.
I'm trying to store the indexes of specific lap times to then proceed to check for the lowest millisecond, in a bigger amount of lap times than just two for example. I have a function for that but it returns only one index number when there are meant to be more.
// code to select minimum lap so far
const minimumLap = {
minimumLapsecond: function() { return lapsecarray.reduce(
(min, currentValue) => Math.min(min, currentValue),
lapsecarray[0]
)},
minimumLapmillisecond: function(){ return lapmilliarray.reduce(
(min, currentValue) => Math.min(min, currentValue),
lapmilliarray[0]
)},
}
lapsecarray.reverse();
lapmilliarray.reverse();
function lapComparison() {
let lapRow = lapTableBody.querySelectorAll("tr");
lapRow.forEach((tr) => tr.classList.remove("min"));
//minimum lap
if (countInArray(lapsecarray)(minimumLap) === 1) {
miniLapindex = lapsecarray.indexOf(minimumLap);
console.log(miniLapindex);
lapRow.item(minLapIndex).classList.add("min");
}
else if (countInArray(lapsecarray)(minimumLapsecond()) > 1) {
minLapIndex = lapmilliarray.indexOf(minimumLapmillisecond());
lapRow.item(minLapIndex).classList.add("min");
}
// counting for multiple seconds or milliseconds in the array to determine which lap time to search
const countInArray = (array) => (value) => {
let count = 0;
for (let i = 0; i <= array.length; i++) {
if (array[i] === value) {
count++;
}
}
return count;
}
// the indexing function that doesn't work as expected 👇
function indexesOf(array) {
let indexes = new Array();
for (let i = 0; i <= array.length; i++) {
if (array.indexOf(i, 0) === value) {
indexes.push(i);
}
}
return indexes;
}
Instead of messing with your code, I have an example idea that you could implement.
First, I strip the colons from the laps. Then I just use Math.min and Math.max to find the min/max from the array.
It might seem like a strange workaround, but without the colons, they just become normal numbers.
laps = ["00:02:03","00:00:42"]; //an array of saved lap times
lap_times = {}; //an empty object that will hold the Numerical Lap time as a key and the string version as the value ie: lap_times[42] = "00:00:42" that way we can grab the original time after determining min/max
laps = laps.map(function(lapTime){//loops through the array and returns a modified value back in each values place
lap = Number(lapTime.replace(/:/g,"")); //replaces the colons and converts to a Number
lap_times[lap] = lapTime //sets the converted time as the key and original time as the value
return lap;
});
/* ... is called spread/rest syntax https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
Without using lap_times[], min/max would return the numerical representation of the time. So by adding it, it will pull back the previously created full string value
*/
slowest = lap_times[Math.max(...laps)];
fastest = lap_times[Math.min(...laps)];
console.log("slowest", slowest,"fastest" , fastest)

node.js: expensive request

Hi, everyone! I need some help in my first app:
I’m creating an application with express+node.js as the background. There is no database. I’m using 3rd-party solution with some functions, that doing calculations, instead.
Front
50 objects. Every object has one unique value: random number. At start I have all these objects, I need to calculate some values for every object and position it on the form based on the calculated results.
Each object sends: axios.get('/calculations?value=uniqueValue') and I accumulate the results in an array. When array.length will be equal 50 I will compare array elements to each other and define (x, y) coordinates of each object. After that, objects will appear on the form.
Back
let value = uniqueValue; // an unique value received from an object
let requests = [];
for (let i = 0; i < 1500; i++) { // this loop is necessary due to application idea
requests.push(calculateData(value)); // 3rd-party function
value += 1250;
}
let result = await Promise.all(requests);
let newData = transform(result); // here I transform the calculated result and then return it.
return newData
Calculations for one object cost 700 ms. All calculations for all 50 objects cost ≈10 seconds. 3rd-party function receives only one value at the same time, but works very quickly. But the loop for (let i = 1; i < 1500; i++) {…} is very expensive.
Issues
10 seconds is not a good result, user can’t wait so long. May be I should change in approach for calculations?
Server is very busy while calculating, and other requests (e.g. axios.get('/getSomething?params=something') are pending.
Any advice will be much appreciated!
You can make the call in chunks of data using async.eachLimit
var values = [];
for (let i = 0; i < 1500; i++) { // this loop is necessary due to application idea
values.push(value);
value += 1250;
}
var arrayOfItemArrays = _.chunk(values, 50);
async.eachLimit(arrayOfItemArrays, 5, eachUpdate, function(err, result){let
newData = transform(result);
return newData ;
});
function eachUpdate(req_arr, cb){
var result = []
req_arr.forEach(fucntion(item){
calculateData(item).then((x){
result.push(x);
});
cb(result);
}

Compute every combination of 6 numbers

I'm more of a media developer and not the best coder, but I find myself needing to learn javascript better. I'm creating a math card game where the human player and the automated player are each dealt 6 cards. Each player must combine (concatenate) three of the cards to make a top number and the other three for the bottom number. Those two numbers are then subtracted. For the automated player, I have to go through ever possible combination of the six cards, so when the two numbers are subtracted, it gets as close as possible to a target number. I'm not very good with arrays, so I started testing every possible combination and then comparing which one was closer (See example below). This is a very inefficient way of coding this, but I'm just not sure how to do it otherwise. Any help would be greatly appreciated.
The variables have already been declared.
alienTopNum = "" + alienNum1 + alienNum2 + alienNum3;
alienBottomNum = "" + alienNum4 + alienNum5 + alienNum6;
oldDiff = targetNum - (alienTopNum - alienBottomNum);
player.SetVar("AC1R1", alienNum1);
player.SetVar("AC2R1", alienNum2);
player.SetVar("AC3R1", alienNum3);
player.SetVar("AC4R1", alienNum4);
player.SetVar("AC4R1", alienNum5);
player.SetVar("AC4R1", alienNum6);
player.SetVar("ATR1", alienTopNum - alienBottomNum);
alienTopNum = "" + alienNum1 + alienNum2 + alienNum3;
alienBottomNum = "" + alienNum4 + alienNum6 + alienNum5;
newDiff = targetNum - (alienTopNum - alienBottomNum);
if (Math.abs(newDiff) < Math.abs(oldDiff)) {
oldDiff = newDiff;
player.SetVar("AC1R1", alienNum1);
player.SetVar("AC2R1", alienNum2);
player.SetVar("AC3R1", alienNum3);
player.SetVar("AC4R1", alienNum4);
player.SetVar("AC4R1", alienNum6);
player.SetVar("AC4R1", alienNum5);
player.SetVar("ATR1", alienTopNum - alienBottomNum);
}
etc....
Store the dealt cards in an array rather than in individual variables, because that makes them a lot easier to handle when generating permutations. You don't say what values the cards can have, but as an example, given a "hand" of [1,2,3,4,5,6] if you get the permutations as an array of arrays:
[ [1,2,3,4,5,6], [1,2,3,4,6,5], [1,2,3,5,4,6], ...etc. ]
Then you can loop through that to process each permutation to take the first three "cards" and last three to get the current iteration's two numbers, subtract them, and see if the result is closer to the target than previous iterations' results.
The following does that, making use of the array permutation function that I found in this answer to another question. I'm not going to explain that algorithm because you can easily google up various permutation algorithms for yourself, but I have put comments in my bestPlay() function to explain how I process the permutations to figure out which is the best score for a hand.
I haven't tried to use your player or player.SetVar() method, but hopefully if you study this you can adapt it to use with your objects.
You didn't say what values the cards could have, so I've assumed a deck of twenty cards that repeats the numbers 0-9 twice.
function bestPlay(hand, target) {
var perms = permutator(hand); // Get all permutations for hand
var best = perms[0]; // Use the first as initial best
var bestDiff = difference(best);
for (var i = 1; i < perms.length; i++) { // Loop over the rest of the permutations
var diff = difference(perms[i]); // Get diff for current permutation
if (Math.abs(target - diff) < Math.abs(target - bestDiff)) { // Check if
best = perms[i]; // current beats previous best
bestDiff = diff; // and if so make it new best
}
}
// Output the results for this hand:
console.log(`Hand: ${hand.join(" ")}`);
console.log(`Best Numbers: ${best.slice(0,3).join("")} ${best.slice(3).join("")}`);
console.log(`Difference: ${bestDiff}`);
}
var hands = deal();
var target = 112;
console.log(`Target: ${target}`);
bestPlay(hands[1], target);
bestPlay(hands[2], target);
function difference(cards) {
return Math.abs(cards.slice(0,3).join("") - cards.slice(3).join(""));
}
function deal() {
var cards = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0];
// shuffle
cards.sort(function() { return Math.random() - 0.5; });
// first hand is first six cards, second hand is next six
return {
1: cards.slice(0,6),
2: cards.slice(6, 12)
};
}
function permutator(inputArr) {
var results = [];
function permute(arr, memo) {
var cur, memo = memo || [];
for (var i = 0; i < arr.length; i++) {
cur = arr.splice(i, 1);
if (arr.length === 0) {
results.push(memo.concat(cur));
}
permute(arr.slice(), memo.concat(cur));
arr.splice(i, 0, cur[0]);
}
return results;
}
return permute(inputArr);
}
If you click the "Run Code Snippet" button several times you'll see that sometimes a given hand has a combination of numbers that exactly matches the target, sometimes it doesn't.

Creating a Javascript function that returns random integers but with a specified distribution/"weight"

I have an array of values:
var my_arr = [/*all kinds of stuff*/]
I have a function that generates a random number, which I use as the index of an element in my_arr...
var RandomFromRange = function (min,max)
{
return Math.floor(Math.random()*(max-min+1)+min);
};
...so I could do stuff like this:
my_arr[RandomFromRange(0,my_arr.length)];
What I want to do is to designate certain elements within my_arr as having "priority", so that RandomFromRange returns 5, say, 25% of the time, returns 4, 14% of the time, and returns any other number...
(100 - 25 - 14)/(my_arr.length - 2)
...% of the time.
As I was doing my research, I came across several posts that describe similar problems, but their answers are not in Javascript, and I, alas, don't have enough math to understand their general principles. Any advice would be appreciated.
This may not be as exact as what you are looking for, but this certainly works. Basically this code returns a random number specified from the min and max like yours, but only after addressing the priority numbers based on the chance given.
First we gotta prioritize your priority numbers in the code. If there is no hit on your priority numbers, that is when we proceed to the normal RNG.
//priority = list of numbers as priority,
//chance = the percentage
//min and max are your parameters
var randomFromRange = function (min,max,priority,chance)
{
var val = null; //initialize value to return
for(var i = 0; i < priority.length; i++){ //loop through priority numbers
var roll = Math.floor(Math.random()*100); //roll the dice (outputs 0-100)
if(chance > roll){ ///check if the chance is greater than the roll output, if true, there's a hit. Less chance value means less likely that the chance value is greater than the roll output
val = priority[i]; //make the current number in the priority loop the value to return;
break; //if there's a hit, stop the loop.
}
else{
continue; //else, keep looping through the priority list
}
}
//if there is no hit to any priority numbers, return a number from the min and max range
if(val == null){
val = Math.floor(Math.random()*(max-min+1)+min);
}
//return the value and do whatever you want with it
return val;
};
document.getElementsByTagName('body')[0].onclick = function (){
console.log(randomFromRange(0,10,[20,30],50));
}
<!DOCTYPE html>
<html>
<body style='height: 1000px; width: 100%;'></body>
<script></script>
</html>
This code applies a single chance on all array of priority numbers. If you want individual chances for each number in the priority list, we gotta modify the structure and change parameters to a single array of objects that holds something like
var priorityList = [{num: 4, chance: 25},
{num: 5, chance: 12}]
etc

dice random value 1 to 10 and overthrow in Javascript

Hi I have code like this:
$('#Generator_Rzutow').click (function(){
var val1 = $('#rzucane').val();
var val2 = $('#zachowywane').val();
var zbior = [];
var limit = 10;
alert (val1);
alert (val2);
for (var i=0; i<val1;i++){
var wynik_rzutu = 1+Math.floor(Math.random()*10);
if (wynik_rzutu<limit){
zbior.push(wynik_rzutu);
} else {
limit = limit+10;
wynik_rzutu = wynik_rzutu+1+Math.floor(Math.random()*10);
if (wynik_rzutu<limit){
zbior.push(wynik_rzutu);
} else {
limit = limit+10;
wynik_rzutu = wynik_rzutu+1+Math.floor(Math.random()*10);
zbior.push(wynik_rzutu);
}
}
}
$('#wypisz').text (zbior);
});
My problem is that when it randoms '10' it sometimes add 10 to array, when it should randomize another time and ad it to prev value.
My second question is. How to get it to randomize another value and ad it to prev as long as it randomize 10. For ex: so it could get numer 74, when it randomize 7x10 and 4, and then it past it to array.
I know I should do it by while lop but I couldn`t get working solition, so instead I put 'if'
The first problem is that you don't reset your limit at each iteration. You start with limit 10, then when the first number larger than 10 is generated, the limit is increased to 20 and all subsequent numbers will be compared to 20 to see if they are added to the array or re-generated (and they will all be added to the array, since they are all smaller than 20).
As for your second problem, i think this piece of code behaves accordingly:
for (var i=0; i<val1;i++){
var wynik_rzutu = 0, limit = 0;
while (wynik_rzutu >= limit) {
wynik_rzutu += 1+Math.floor(Math.random()*10);
limit += 10;
}
zbior.push(wynik_rzutu);
}
You can also add a counter to prevent it from an infinite cycle (if Math.random() always returns 0.9 for example), but i doubt it is something you really require.

Categories

Resources