minimize of sum in javascript in two dimension array - javascript
I am trying to solve below problem ,my one test case fail why ?
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Input:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
Output: 7
Explanation: Because the path 1→3→1→1→1 minimizes the sum.
/**
* #param {number[][]} grid
* #return {number}
*/
var minPathSum = function(grid) {
let firstRow = 0,
firstColumn = 0,
endColumn = 0,
endRow = 0;
if(grid.length === 1){
return grid[0][0]
}
let firstArray = grid[0];
let endArray = grid[grid.length - 1];
firstArray.forEach((i) => firstRow += i);
endArray.forEach((i) => endRow += i);
for (let i = 1; i < grid.length - 1; i++) {
firstColumn += grid[i].shift();
endColumn += grid[i].pop()
}
let cornEdge = grid[grid.length - 1].pop();
let firstElemt = grid[0].shift();
if (firstRow + endColumn + cornEdge> firstElemt + firstColumn + endRow) {
return firstElemt+ firstColumn + endRow
} else {
return firstRow + endColumn +cornEdge
}
};
failed test case
Input
[[1,2,5],[3,2,1]]
Output
7
Expected
6
from my point of view above expectation is wrong ? it should be 7 using 1->3->2->1 but how it is six
This is a brute force solution to the problem. It will recursively iterate every possible path through the array, and return the minimum found.
Unfortunately, whilst it works with the two test cases presented in the question, it exceeds the runtime execution limits on Leetcode for the more complex cases; although it does still yield an answer. For example:
minPathSum([
[3,8,6,0,5,9,9,6,3,4,0,5,7,3,9,3],
[0,9,2,5,5,4,9,1,4,6,9,5,6,7,3,2],
[8,2,2,3,3,3,1,6,9,1,1,6,6,2,1,9],
[1,3,6,9,9,5,0,3,4,9,1,0,9,6,2,7],
[8,6,2,2,1,3,0,0,7,2,7,5,4,8,4,8],
[4,1,9,5,8,9,9,2,0,2,5,1,8,7,0,9],
[6,2,1,7,8,1,8,5,5,7,0,2,5,7,2,1],
[8,1,7,6,2,8,1,2,2,6,4,0,5,4,1,3],
[9,2,1,7,6,1,4,3,8,6,5,5,3,9,7,3],
[0,6,0,2,4,3,7,6,1,3,8,6,9,0,0,8],
[4,3,7,2,4,3,6,4,0,3,9,5,3,6,9,3],
[2,1,8,8,4,5,6,5,8,7,3,7,7,5,8,3],
[0,7,6,6,1,2,0,3,5,0,8,0,8,7,4,3],
[0,4,3,4,9,0,1,9,7,7,8,6,4,6,9,5],
[6,5,1,9,9,2,2,7,4,2,7,2,2,3,7,2],
[7,1,9,6,1,2,7,0,9,6,6,4,4,5,1,0],
[3,4,9,2,8,3,1,2,6,9,7,0,2,4,2,0],
[5,1,8,8,4,6,8,5,2,4,1,6,2,2,9,7]
]);
// 83 = 3+0+8+2+2+3+3+3+1+0+0+0+2+0+2+5+0+2+0+5+4+1+3+3+8+3+3+3+5+2+0+0+7
const minPathSum = function(grid) {
let maxX = grid[0].length - 1;
let maxY = grid.length - 1;
return mapPath(grid, 0, 0, maxX, maxY, 0);
};
const mapPath = function(grid, x, y, maxX, maxY, length) {
const value = grid[y][x];
if (x === maxX && y === maxY) {
return length + value;
}
const minX = (x < maxX)
? mapPath(grid, x + 1, y, maxX, maxY, length + value)
: Infinity;
const minY = (y < maxY)
? mapPath(grid, x, y + 1, maxX, maxY, length + value)
: Infinity;
return Math.min(minX, minY);
};
console.log(minPathSum([[1,3,1],[1,5,1],[4,2,1]]));
console.log(minPathSum([[1,2,5],[3,2,1]]));
You should do like:
function min(array){
return Math.min(...array);
}
function sum(array){
return array.reduce((a, c)=>a+=c);
}
function sumsMin(arrayOfArrays){
const sums = [];
arrayOfArrays.forEach(a=>{
sums.push(sum(a));
});
return min(sums);
}
console.log(sumsMin([[1,2,5],[3,2,1]]));
Related
Get reverse of an equation - JavaScript
Let's say I have this formula, for example: function getExperience(level) { let a = 0; for (let x = 1; x < level; x += 1) { a += Math.floor(x + (200 * (2 ** (x / 3)))); } return Math.floor(a / 4); } for (var i = 1; i < 100; i++) { console.log(`Level ${i}: ${getExperience(i)}`); } To get the experience needed for level 50, you'd do: getExperience(50). But, how would you reverse that and get the LEVEL needed for experience? So, getLevel(20010272) would output 50.
Short answer You can use 4.328085 * Math.log(0.00519842 * xp + 1.259921045) as a very good approximation of the corresponding level. If you need an exact value, you could iterate over all levels until you find the desired range, as in this answer. Long answer Slightly modified function I don't think it's possible to find an exact, closed-form expression for the inverse of this function. It should be possible if you modify getExperience(level) a bit, though. First, you can notice that x grows much slower than 2 ** (x / 3). Then, Math.floor doesn't have much influence over large numbers. So let's remove them! Here's the slightly modified function: function getExperienceEstimate(level) { let a = 0; for (let x = 1; x < level; x += 1) { a += 200 * (2 ** (x / 3)); } return a / 4; } The advantage of this method is that it's now a geometric series, so it's possible to calculate the sum directly, without any loop: function getExperienceEstimate(level) { let a = 50; let r = 2 ** (1 / 3); return a * (r**level - r) / (r - 1); }; getExperienceEstimate(50) returns 20011971.993575357, which is only 0.0015% smaller than getExperience(50). Inverse function According to Wolfram Alpha, here's the inverse function of getExperienceEstimate: function getLevelEstimate(xp){ let a = 50; let r = 2 ** (1 / 3); return Math.log(xp * (r - 1) / a + r) / Math.log(r); }; With some minor precision loss, you can simplify it further: function getLevelEstimate(xp){ return 4.328085 * Math.log(0.00519842 * xp + 1.259921045) }; It's only an estimate, but it works pretty well and doesn't require any loop! Test For 20012272 XP, the approximate inverse function returns 50.00006263463371, which should be a good starting point if you want to find the exact result. function getExperience(level) { let a = 0; for (let x = 1; x < level; x += 1) { a += Math.floor(x + (200 * (2 ** (x / 3)))); } return Math.floor(a / 4); } function getLevelEstimate(xp){ return 4.328085 * Math.log(0.00519842 * xp + 1.259921045) }; for (var i = 1; i < 100; i++) { console.log(`Level ${i} (XP = ${getExperience(i)}). Estimated level : ${getLevelEstimate(getExperience(i))}`); }
You can use a binary search algorithm to avoid to loop over all possibilities. Here is an example that I have adapted to your case. You first need to create an array to map all your level => experience, this action should be done only ONCE, then you never have to do it again. As you can see in my example, even with 1000 levels, you never have to iterate more than 9 times whatever level you are trying to find. // You first have to create an array with all your levels. // This has to be done only ONCE because it's an expensive one! const list = []; for (let i = 1; i <= 1000; i++) { list[i] = getExperience(i); } function getExperience(level) { let a = 0; for (let x = 1; x < level; x += 1) { a += Math.floor(x + (200 * (2 ** (x / 3)))); } return Math.floor(a / 4); } function getLevel(value) { // initial values for start, middle and end let start = 0 let stop = list.length - 1 let middle = Math.floor((start + stop) / 2) let iterations = 0; // While the middle is not what we're looking for and the list does not have a single item. while (list[middle] !== value && start < stop) { iterations++; if (value < list[middle]) { stop = middle - 1 } else { start = middle + 1 } // Recalculate middle on every iteration. middle = Math.floor((start + stop) / 2) } console.log(`${value} is Level ${middle} (Result found after ${iterations} iterations)`); return middle; } // Then you can search your level according to the experience getLevel(0); getLevel(72); getLevel(20010272); getLevel(getExperience(50)); getLevel(33578608987644589722);
A brute-force (but inelegant) solution would be to just call getExperience for levels until you reach a level that requires more experience than the passed exp: function getLevel(exp) { if (exp === 0) return 0; let level = 0; let calcExp = 0; while (exp > calcExp) { calcExp = getExperience(level); if (calcExp > exp) break; level++; } return level - 1; } console.log(getLevel(20012272)); // experience required for 50 on the dot console.log(getLevel(20012270)); console.log(getLevel(20012274)); console.log(getLevel(0)); function getExperience(level) { let a = 0; for (let x = 1; x < level; x += 1) { a += Math.floor(x + (200 * (2 ** (x / 3)))); } return Math.floor(a / 4); }
You can use binary search to locate level value faster - in 7 steps max. (while I doubt that gain is significant for length 100 list)
How to calculate the square root without using library and built-in methods in Javascript?
Please help me to write a function to compute the square root of positive real numbers using the formula: x i+1 = (1/2) * (xi + (A / x1)), where 'A' - input real number. On the zero iteration next statements have been taken x0 = A The error should be at least 10-6 Output sqrt (2) = 1.414 sqrt (9) = 3 sqrt (25) = 5
You could take xi (x) and the new value of xi + 1 (x1) and check if the values are equal. Then end the series and return that value. For starting, you need an apporopriate value like the half of the given value. function sqrt(a) { var x, x1 = a / 2; do { x = x1; x1 = (x + (a / x)) / 2; } while (x !== x1); return x; } console.log(sqrt (2)); // 1.414 console.log(sqrt (9)); // 3 console.log(sqrt (25)); // 5
You can also use bisection - a more general method for solving problems: var sqrt = function(n) { if (n<0) { throw "are you kidding?! we are REAL here."; } if (n === 0) { return 0; } var bisect = function(l,r) { var avg = (l+r)/2; if (r-l<0.00000001) { return (l+r)/2; } if (avg*avg > n) { return bisect(l, avg); } else if (avg*avg < n) { return bisect(avg, r); } } return bisect(0, n < 1 ? 1 : n); }
Find the closest index to given value [duplicate]
This question already has answers here: Get the closest number out of an array (21 answers) Closed 7 years ago. I have an ordered array: btnDrag.pos = [0, 65, 131, 196, 259, 323, 388, 453, 517]; And a function that fires when drag stops: btnDrag.draggable({ axis: 'x', containment: 'parent', stop: function() { var index = (function(){ var new_x = btnDrag.position().left; // now, how to find the closest index in btnDrag.pos relative to new_x ? // return index; })(); btnDrag.animate({ 'left': (btnDrag.pos[index] + 'px') }); } }); The array values are points which btnDrag is allowed to stay (in axis 'x'). So, the function must return the closest index with the value to btnDrag go. Thanks in advance.
Since your array is sorted, the fastest way is to use a modified version of the binary search algorithm: function closest (arr, x) { /* lb is the lower bound and ub the upper bound defining a subarray or arr. */ var lb = 0, ub = arr.length - 1; /* We loop as long as x is in inside our subarray and the length of our subarray is greater than 0 (lb < ub). */ while (ub - lb > 1) { var m = parseInt((ub - lb + 1) / 2); // The middle value /* Depending on the middle value of our subarray, we update the bound. */ if (arr[lb + m] > x) { ub = lb + m; } else if (arr[lb + m] < x) { lb = lb + m; } else { ub = lb + m; lb = lb + m; } } /* After the loop, we know that the closest value is either the one at the lower or upper bound (may be the same if x is in arr). */ var clst = lb; if (abs(arr[lb] - x) > abs(arr[ub] - x)) { clst = ub; } return clst; // If you want the value instead of the index, return arr[clst] } Here is a fiddle where you can test it: http://jsfiddle.net/Lpzndcbm/4/ Unlike all the solution proposed here this solution runs in O(log(n)) and not in O(n). If you are not familiar with complexity, it means that this algorithm will find the closest value in an array of size N in at most O(log(N)) loop while the others will find it in at most N loop (with N = 10000, it makes a big difference since log(10000) ~ 14 (binary log)). Note that if you have really small array, this may be slower than the naive algorithm.
There you go : function closest(list, x) { var min, chosen = 0; for (var i in list) { min = Math.abs(list[chosen] - x); if (Math.abs(list[i] - x) < min) { chosen = i; } } return chosen; } Each time, the minimum distance is computed and the chosen value is updated based on the minimum. (http://jsbin.com/dehifefuca/edit?js,console)
Something like this? var closest = btnDrag.pos.reduce(function (prev, curr) { return (Math.abs(curr - new_x) < Math.abs(prev - new_x) ? curr : prev); });
Simple for loop will do it: var btnDrag = {}; btnDrag['pos'] = [0, 65, 131, 196, 259, 323, 388, 453, 517]; new_x = 425; var index = -1; for (var i = 0; i < btnDrag.pos.length; i++) { if (i < btnDrag.pos.length-1) //loop till i is at 2 positions from the end. { //value has to be less then the selected value + 1 if (new_x < btnDrag.pos[i+1]) { //calculate the half between the values and add it with the first value // test if new_x is larger then that value. if ((btnDrag.pos[i+1] - btnDrag.pos[i])/2 + btnDrag.pos[i] > new_x) { index = i; break; } else { index = i+1; break; } } } else { //edge cases. if (new_x < 0) { index = 0; } else { index = btnDrag.pos.length-1; } } } document.body.innerHTML = btnDrag['pos'][index] + " (" + index + ")";
How to use Javascript class for xirr formula
Hello I have found a javascript class for some excel functions but i dont know how to use it. I need to use XIRR function but i dont know the type and format of parameters and the syntax. Here is the code: /* Based on * - EGM Mathematical Finance class by Enrique Garcia M. <egarcia#egm.co> * - A Guide to the PMT, FV, IPMT and PPMT Functions by Kevin (aka MWVisa1) */ var ExcelFormulas = { PVIF: function(rate, nper) { return Math.pow(1 + rate, nper); }, FVIFA: function(rate, nper) { return rate == 0? nper: (this.PVIF(rate, nper) - 1) / rate; }, PMT: function(rate, nper, pv, fv, type) { if (!fv) fv = 0; if (!type) type = 0; if (rate == 0) return -(pv + fv)/nper; var pvif = Math.pow(1 + rate, nper); var pmt = rate / (pvif - 1) * -(pv * pvif + fv); if (type == 1) { pmt /= (1 + rate); }; return pmt; }, IPMT: function(pv, pmt, rate, per) { var tmp = Math.pow(1 + rate, per); return 0 - (pv * tmp * rate + pmt * (tmp - 1)); }, PPMT: function(rate, per, nper, pv, fv, type) { if (per < 1 || (per >= nper + 1)) return null; var pmt = this.PMT(rate, nper, pv, fv, type); var ipmt = this.IPMT(pv, pmt, rate, per - 1); return pmt - ipmt; }, DaysBetween: function(date1, date2) { var oneDay = 24*60*60*1000; return Math.round(Math.abs((date1.getTime() - date2.getTime())/oneDay)); }, // Change Date and Flow to date and value fields you use XNPV: function(rate, values) { var xnpv = 0.0; var firstDate = new Date(values[0].Date); for (var key in values) { var tmp = values[key]; var value = tmp.Flow; var date = new Date(tmp.Date); xnpv += value / Math.pow(1 + rate, this.DaysBetween(firstDate, date)/365); }; return xnpv; }, XIRR: function(values, guess) { if (!guess) guess = 0.1; var x1 = 0.0; var x2 = guess; var f1 = this.XNPV(x1, values); var f2 = this.XNPV(x2, values); for (var i = 0; i < 100; i++) { if ((f1 * f2) < 0.0) break; if (Math.abs(f1) < Math.abs(f2)) { f1 = this.XNPV(x1 += 1.6 * (x1 - x2), values); } else { f2 = this.XNPV(x2 += 1.6 * (x2 - x1), values); } }; if ((f1 * f2) > 0.0) return null; var f = this.XNPV(x1, values); if (f < 0.0) { var rtb = x1; var dx = x2 - x1; } else { var rtb = x2; var dx = x1 - x2; }; for (var i = 0; i < 100; i++) { dx *= 0.5; var x_mid = rtb + dx; var f_mid = this.XNPV(x_mid, values); if (f_mid <= 0.0) rtb = x_mid; if ((Math.abs(f_mid) < 1.0e-6) || (Math.abs(dx) < 1.0e-6)) return x_mid; }; return null; } };
You want to use XIRR, so let's look at its signature: XIRR: function(values, guess) What does it do with values? var f1 = this.XNPV(x1, values); So values must be whatever XNPV is expecting. It has this chunk at its core: for (var key in values) { var tmp = values[key]; var value = tmp.Flow; var date = new Date(tmp.Date); xnpv += value / Math.pow(1 + rate, this.DaysBetween(firstDate, date)/365); }; So it is expecting values to be a dictionary (associative array), where the value part of the key-value pair has members .Flow and .Date. I assume .Flow is the cashflow, and from the DaysBetween method I can see that .Date is a javascript Date. The key is ignored, so it can be a numeric if we want. So let's make one of those: var myInstrument = { 0: {Flow: 5, Date: new Date(2015, 7, 6)}, 1: {Flow: 105, Date: new Date(2016, 7, 6)} }; (That is a dictionary (or array) declaration). The other input to XIRR is guess, which it will use to solve something, but it will default to using 0.1 (10% !) if given a falsy input value. So we can call it with our myInstrument thus: var myInternalReturn = XIRR(myInstrument, false); NB: The XIRR function is implementing the Actual/365 Fixed day count convention for Annual payment frequency, which may not be appropriate for the instrument you are valuing. Maybe it won't make much difference, but it will be incorrect for semi-annual or 30/360, with particular problems around month-end dates, simple interest instruments and so on
In an array, how do I find the closest key given a float value?
I'm making an "acceleration" array like this: acc["0100"] = 1; acc["0300"] = 2; acc["0600"] = 4; acc["0900"] = 8; acc["2000"] = 16; acc["5000"] = 32; And, when the user presses a key, I start a timer: this._startTick = (new Date()).getTime(); Now I have a timer that checks if the key is still pressed. If so, then I do something like: this._delay = (new Date()).getTime() - this._startTick; And now, based on this._delay, I'd like to find one of the previous values (1, 2, 4 or 8). How would you do that? NB: if the value is greater than "5.0" then the result should always be 32. NOTA: my goal is, given an elapsed time, find out which value is the best. I started the way I've just explained, but if you have another solution, I'll take it!
It's easier to operate on an array than on an object: var accArr = []; for (time in acc) { accArr.push({time: time, value: acc[time]}); } Assuming you have an array, you can do: function getValue(delay) { var diffs = accArr.map(function (e) { return Math.abs(e.time - delay); }); return accArr[diffs.indexOf(Math.min.apply(null, diffs))].value; } EDIT: Well, you didn't mention that this is a performance-critical function. In that case, I would recommend picking a granularity (e.g. 0.05, so the multiplier for delay is 20) and pre-calculating all values from 0 to MAX_DELAY: var multiplier = 20, granularity = 1 / multiplier; var delayValues = (function () { var result = []; for (var delay = 0; delay <= MAX_DELAY; delay += granularity) { result.push(getValue(delay)); } return result; })(); During the animation, fetching the value will be a simple lookup in a relatively small table: function getValueFast(delay) { return (delayValues[Math.round(delay * multiplier)] || delayValues[delayValues.length - 1]) } JSPerf comparison between this solution and simple if statements shows they perform equally fast for searching around a middle value.
Here is the jsfiddle test page. var getAccForDelay = (function () { var acc = { 0.1: 1, 0.3: 2, 0.6: 4, 0.9: 8, 2.0: 16, 5.0: 32 }; return function(delay) { var key, bestKey = undefined, absDiff, absDiffMin = Number.MAX_VALUE; for (key in acc) { if (acc.hasOwnProperty(key)) { absDiff = Math.abs(delay - key); if (absDiffMin > absDiff) { absDiffMin = absDiff; bestKey = key; } } } return bestKey === undefined ? undefined : acc[bestKey]; }; }()); Test: console.clear(); console.log(getAccForDelay(0)); console.log(getAccForDelay(0.33)); console.log(getAccForDelay(3.14)); console.log(getAccForDelay(123456.789)); Output: 1 2 16 32 === UPDATE === The above solution doesn't utilize of the fact that acc is sorted by key. I optimized the code by replacing linear search with binary search, which is much faster on long arrays. Here is the test page. var getAccForDelay = (function () { var accKey = [ 0.1, 0.3, 0.6, 0.9, 2.0, 5.0 ], accValue = [ 1, 2, 4, 8, 16, 32 ], accLength = accKey.length; return function(delay) { var iLeft, iMiddle, iRight; iLeft = 0; if (delay <= accKey[iLeft]) return accValue[iLeft]; iRight = accLength - 1; if (accKey[iRight] <= delay) return accValue[iRight]; while (true) { if (iRight - iLeft === 1) return delay - accKey[iLeft] < accKey[iRight] - delay ? accValue[iLeft] : accValue[iRight]; iMiddle = ~~((iLeft + iRight) / 2); if (delay < accKey[iMiddle]) iRight = iMiddle; else if (accKey[iMiddle] < delay) iLeft = iMiddle; else return accValue[iMiddle]; } }; }());
In my humble opinion I think the best solution to this problem is to write a function which picks the best acceleration based on the time using if statements as follows: function getAcceleration(time) { if (time < 0.20) return 1; if (time < 0.45) return 2; if (time < 0.75) return 4; if (time < 1.45) return 8; if (time < 3.50) return 16; return 32; } However this is a static solution. If that's alright with you then I recommend you use this method. On the other hand if you need a dynamic solution then use this instead: var getAcceleration = createAccelerationMap(0.1, 0.3, 0.6, 0.9, 2.0, 5.0); function createAccelerationMap(previous) { var length = arguments.length, limits = []; for (var i = 1; i < length;) { var current = arguments[i++]; limits.push((previous + current) / 2); previous = current; } return function (time) { var length = limits.length, acceleration = 1; for (var i = 0; i < length;) { if (time < limits[i++]) return acceleration; acceleration *= 2; } return acceleration; }; } Either way you may then use getAcceleration as follows: console.log(getAcceleration(0)); // 1 console.log(getAcceleration(0.33)); // 2 console.log(getAcceleration(0.64)); // 4 console.log(getAcceleration(1.42)); // 8 console.log(getAcceleration(3.14)); // 16 console.log(getAcceleration(123456.789)); // 32 See the demo: http://jsfiddle.net/QepT7/
If the 0.1 is the number of seconds, and you want to round to 1 decimal you can do something this: // 0.42332 * 10 = 4.2332 // Math.round( ) will be 4 // 4 / 10 = 0.4 acc[ (Math.round(this._delay * 10) / 10).toString() ]
var seconds = this._delay.toString().substring(0,2) console.log(acc[seconds]); This is a straight-forward approach of your problem: First I convert the float to a string, second I cut off everything after the third character.
What units are you using? this._startTick = (new Date()).getTime(); // ms = ms this._delay = (new Date()).getTime() - this._startTick; // ms = ms - ms So to get to "0.1"/etc from milliseconds I'm assuming you are doing (Math.floor(ms / 100) / 10).toString(); Why not just keep everything in ms/100 so you can use integers? var acc = []; acc[ 1] = 1; acc[ 3] = 2; acc[ 6] = 4; acc[ 9] = 8; acc[20] = 16; acc[50] = 32; Then you can create a "nearest" lookup function like this function find(x) { var i = 0; x = x | 0; // The | 0 will cause a cast to int if (x < 0) x = 0; if (acc[x] !== undefined) return acc[x]; if (x > acc.length) return acc[acc.length - 1]; while (++i < acc.length) { if (acc[x - i] !== undefined) return acc[x - i]; if (acc[x + i] !== undefined) return acc[x + i]; } } find(this._delay / 100); Now examples are find(30); // 16 find(100.5); // 32 find(0); // 1