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]]));
If you want to choose a random number between 190 and 255, expecting evenly distributed results, the code you need is as simple as the following, correct?
190 + Math.floor(Math.random() * 66);
But what if you prefer unevenly distributed results between 190 and 255? I mean, for instance, the closer a number is to the lower end of the range (i.e. 190), the higher the possibility of the number being chosen.
Let us suppose that the code returns a random number:
between 190 and 210 with a 70% probability.
between 211 and 230 with a 20% probability.
between 231 and 255 with a 10% probability.
I think that the uneven distribution like this adds an interesting flavour to the act of choosing a random number.
I've written the code for this in two different ways, the second one taking a more complex form. I started to learn programming just several days ago, so I've written them, drawing on what little I know of JavaScript at the moment. I wonder if I can express them more efficiently.
Incidentally, I have one specific question in mind:
In the 1st Code, do I need to place var in front of attackPoint = midRange and attackPoint = highRange in the if/else statement?
1st Code:
var lowRange = 190 + Math.floor(Math.random() * 21);
var midRange = 211 + Math.floor(Math.random() * 20);
var highRange = 231 + Math.floor(Math.random() * 25);
var randomHundred = 1 + Math.floor(Math.random() * 100);
if (randomHundred <= 70) {
var attackPoint = lowRange;
}
else if (randomHundred <= 90) {
var attackPoint = midRange;
}
else {
var attackPoint = highRange;
}
console.log(attackPoint);
2nd Code:
var lowRange = 190 + Math.floor(Math.random() * 21);
var midRange = 211 + Math.floor(Math.random() * 20);
var highRange = 231 + Math.floor(Math.random() * 25);
var emptyArray = [];
for (var i = 0; i < 100; i++) {
if (i < 70) {
emptyArray.push(lowRange);
}
else if (i < 90) {
emptyArray.push(midRange);
}
else {
emptyArray.push(highRange);
}
};
var attackPoint = emptyArray[Math.floor(Math.random() * 100)];
console.log(attackPoint);
The 1st way improvement:
You don't need to calculate random values for all ranges, you only need the selected range. Also it's unnecessary to cast 0..1 range to 0..100. You can deal with 0..1 range directly.
var q = Math.random(), attackPoint;
if (q < 0.7) {
attackPoint = 190 + Math.floor(Math.random() * 21);
}
else if (q < 0.9) {
attackPoint = 211 + Math.floor(Math.random() * 20);
}
else {
attackPoint = 231 + Math.floor(Math.random() * 25);
}
console.log(attackPoint);
On your specific point, I am not a Javascript expert, but I think you need:
var attackPoint; // Declare, but do no initialize the variable.
if (randomHundred <= 70) {
attackPoint = lowRange;
}
else if (randomHundred <= 90) {
attackPoint = midRange;
}
else {
attackPoint = highRange;
}
A more efficient way is going to involve "stretching" the range you want to be more likely, and then choosing randomly. Something like:
var attackValues = []
for (var i = 190; i < 211; i++) {
for (var j = 0; j < 7; j++) {
attackValue.push(i); // Seven values here.
}
}
for (var i = 211; i < 231; i++) {
attackValue.push(i); attackValue.push(i); // Two values here
}
for (var i = 231; i < 256; i++) {
attackValue.push(i); // Just one value here.
}
// The attackValue array could be calculated once and stored for repeated
// use if your inflection points stay constant.
var attackPoint = attackValue[ Math.floor(Math.random() * attackValue.length) ]
The idea is to fill attackValue array with the possible results, putting in multiple copies of the values you want more often, and then choosing one at random.
Another approach is to do something like square the random value, and then convert to integer. Squaring makes smaller values more likely in a somoother way than adding specific inflexion points. Depending on your application, that may be better (or not).
Just from a programming style it is good form to separate the table of probabilities from the logic that generates the random numbers. The reason being that the exact details of the probabilities and ranges are likely to change over time, but the idea of a weighted random number will stay constant. So once you've got the weighted random number code changing, you don't want to have to change it time and again:
var table = [
{ probability:70, low:190, hi: 210},
{ probability:20, low:211, hi: 230},
{ probability:10, low:231, hi: 255}
]
function weightedRandom(table) {
var total = table.reduce(function(sum, line) {
return sum + line.probability;
}, 0);
var select = Math.floor(Math.random() * total);
for (var i = 0; i < table.length; i++) {
var line = table[i];
select -= table[i].probability;
if (select < 0) {
return (Math.floor(Math.random() * (line.hi - line.low)) +
line.low;)
}
}
}
for (var i = 0; i < 10; i++) {
console.log(weightedRandom(table));
}
NOTE: you could simplify the above code if you assume that the probabilities will always add to 100.
When I run this I get:
237
228
239
209
193
218
213
193
245
214
which seems correct.
I think this might be a possible solution too:
var number = Math.random();
var index = Math.floor(number * 66) + 190;
//answer:
console.log(Math.floor(number * dist(index) * 66) + 190);
function dist(index) {
var retValue;
if (index < 210) {
retValue = .7;
}
else if (number >= 210 && number < 230) {
retValue = .2;
}
else {
retValue = .1;
}
return retValue;
}
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 + ")";
I have a simple implementation question.
Here is the random number function I have, and returns a random number from a given range, inclusive.
function randomNum(low, high){
return Math.floor(Math.random() * (high - low + 1)) + low;
}
However, I would like to have 50% chance of getting the high number, and 25% for everything else..
for example:
randomNum(1, 3)
'3' would have a 50% chance of getting a hit, while '1' and '2' will both have a hit percentage of 25%.
I'm not too sure as to what changes I need to make to my function...tips would be great, Thanks
function randomNum(low, high){
return Math.random() > 0.5 ?
high :
Math.floor(Math.random() * (high - low)) + low;
}
In a generic manner; I suppose you're after a weighted random number generator:
function weightedRandomNumber(weights) {
var sum = 0;
for (var w in weights) {
w = weights[w];
sum += w.weight;
}
var rand = Math.random() * sum;
for (var w in weights) {
w = weights[w];
if (rand < w.weight) {
return w.value;
}
rand -= w.weight;
}
return weights[weights.length - 1].value;
}
Test:
var config = [
{ weight: 25, value: 1 },
{ weight: 25, value: 2 },
{ weight: 50, value: 3 }
];
var test = { 1: 0, 2: 0, 3: 0 }, max = 10000;
for (var i = 1; i < max; i += 1) {
test[weightedRandomNumber(config).toString()] += 1;
}
alert('From ' + max + ' rounds; results: ' + JSON.stringify(test));
Make if else condition
If it is 3 its ok or else if it is not 3 then again make a random number between 1 and 2;
Hence the 3 will get 50% chances where as 1,2 will get 25% chances
There are two approaches that you can use. (1) You can have array of value and random the index of value to get. If you want certain number to have higher chance, just put it more. For example:
var arr = [1, 2, 3, 3];
return arr[Math.floor(Math.random() * arr.length)];
(2) Second approach is doing the array shuffling.
var arr[1, 2, 3, 3];
shuffle(arr);
return arr[0];
This should work:
function randomNum(low, high){
var mid = (low + high)/2;
var randomn = Math.floor(Math.random() * (high - low + 1)) + low;
if(randomn > mid)
return randomn ;
else
return Math.floor(Math.random() * (high - low + 1)) + low;
}
here you go. high will have 50% chance, the rest will split the other 50% equally
function randomNum(low, high)
{
var myarry = []
for(var i=0;i<(high-low);i++) { myarry.push(low+i) } ; //var myarry=[low, low+1, ....,high-1] excludes high
console.log(myarry)
var magic=Math.random();
var index=Math.round(magic*(high-low)); // Gaurantee the chance is split between the elements of the array
return Math.round(magic)==1?high:myarry[index] // Guaranteed 50% chance for high either 0 or 1, the rest will split the chance
}
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