Leetcode Test case Fail - javascript

I am trying to solve a leetcode [problem][1]. The question says to search in a 2d array. While my code passes for most of the test cases it fails for a particular test case.
/**
* #param {number[][]} matrix
* #param {number} target
* #return {boolean}
*/
/**
* #param {number[][]} matrix
* #param {number} target
* #return {boolean}
*/
var searchMatrix = function(matrix, target) {
let i = 0 ;
let j = matrix.length ;
while(i <= matrix.length - 1 && j >= 0){
if(matrix[i][j] == target){
return true
}
if(matrix[i][j] > target){
j--;
} else {
i++;
}
}
return false
};
searchMatrix([1,3],3)
Above solution gives false whereas the correct answer should be true. What's wrong here ? Cant find out !
[1]: https://leetcode.com/problems/search-a-2d-matrix/

This question has two variations one on Leetcode and another on Geeks for Geeks.
Your solution above would work for GFG platform but would fail on leetcode.
Why?
Variation in both question lies how elements are arranged. In leetcode question first element of every row will be greater than last element of the previous row, which is not in the case of GFG. On GFG you will have row and column wise sorted matrix.
Your solution would pass the GFG test cases but would fail on leetcode. Hence one of the optimized solutions that you can go with is to use its question property and imagine it as a one dimensional array.
function searchMatrix(matrix, target){
let numberOfRows = matrix.length
let numberOFColums = matrix[0].length
let upperBoundOfMatrix = numberOfRows * numberOFColums - 1;
let start = 0
while(start <= upperBoundOfMatrix){
let mid = Math.floor(start + (upperBoundOfMatrix - start)/2);
let row = Math.floor(mid/numberOFColums);
let column = Math.floor(mid % numberOFColums);
if(matrix[row][column] == target){
return true
}
if(matrix[row][column] > target){
upperBoundOfMatrix = mid - 1;
} else {
start = mid + 1;
}
}
return false
}

Related

LeetCode javascript Palindrome DONE but still getting wrong output

/**
* #param {number} x
* #return {boolean}
*/
var isPalindrome = function(x) {
var y=x,num=0,rem;
while(x>0)
{
rem=x%10;
num=(num*10)+rem;
x=x/10;
}
if(num==y)
return true;
else
return false ;
};
I am still getting wrong output as false but my logic is correct.
This is leetcode palindrome question i am trying it with javascript logic is correct but still not able to figure it out.
There is just one issue:
In JavaScript numbers are floating point numbers by default, and so / performs a floating point division. You need to truncate that:
x = Math.floor(x / 10);
A remark on your code:
The construct if (boolean) return true; else false is an anti-pattern. Since boolean already represents the value you want to return, you should just return it. So in your case do:
return num == y;
Your logic seems fine but execution is having some minor errors. Please use below snippet, it should work:
var isPalindrome = function(x) {
if (x < 0) {
return false;
}
// Store the number in a variable
let number = x;
// This will store the reverse of the number
let reverse = 0;
while (number > 0) {
reverse = reverse * 10 + number % 10;
number = parseInt(number / 10);
}
return x === reverse;
}

Javascript calculate percentage consistency of an array of values

I am trying to calculate the consistency of an array of values which output a percentage. So for example an array of [1,1,1,1,1] would output 100% consistency, and array of [1,12,23,5,2] would output something like 25% consistency.
I have tried a simple percentage difference calculation but is only for two numbers whereas this needs to work for a dynamic array and this only outputs the difference. Any help would be appreciated so thanks in advance.
function getPercentage(n1, n2){
var newValue = n1 - n2;
return (newValue / n1) * 100;
}
getPercentage(1, 12)
Based on your comments, I refined the base value used in calculating the overall consistency between members of the array.
The new results calculated (which on visual inspection seems plausible, again it depends on the definition of consistency over all members but I think this is getting closer):
$ node jsscratch.js
Consistency for 1,1,1,1,1 is 100.000% fixed to 3 decimal places
Consistency for 1,12,23,5,2 is 33.360% fixed to 3 decimal places
Consistency for 1,12,23,15,12 is 50.160% fixed to 3 decimal places
Consistency for 1,2,10 is 83.778% fixed to 3 decimal places
/**
* Calculate the expected value
*/
function expectancy(arrayOfValues) {
let sumTotal = function(previousValue, currentValue) {
return previousValue + currentValue;
};
let u = arrayOfValues.reduce(sumTotal);
// Assume each member carries an equal weight in expected value
u = u / arrayOfValues.length;
return u;
}
/**
* Calculate consistency of the members in the vector
* #param {Array<number>} The vector of members to inspect for similarity
* #return {number} The percentage of members that are the same
*/
var similarity = function(arrayOfValues) {
let sumTotal = function(previousValue, currentValue) {
return previousValue + currentValue;
};
// Step 1: Calculate the mean value u
let u = expectancy(arrayOfValues); // Calculate the average
// Step 2: Calculate the standard deviation sig
let sig = [];
let N = 1/arrayOfValues.length;
for (let i = 0; i < arrayOfValues.length; i++) {
sig.push(N*(arrayOfValues[i] - u) * (arrayOfValues[i] - u));
}
// This only works in mutable type, such as found in JavaScript, else sum it up
sig = sig.reduce(sumTotal);
// Step 3: Offset from 100% to get the similarity
return 100 - sig;
}
answer = similarity(ar1);
console.log(`Consistency for ${ar1} is ${answer.toFixed(3)}% fixed to 3 decimal places`);
answer = similarity(ar2);
console.log(`Consistency for ${ar2} is ${answer.toFixed(3)}% fixed to 3 decimal places`);
answer = similarity(ar3);
console.log(`Consistency for ${ar3} is ${answer.toFixed(3)}% fixed to 3 decimal places`);
answer = similarity(ar4);
console.log(`Consistency for ${ar4} is ${answer.toFixed(3)}% fixed to 3 decimal places`);
Ok this is my first stab I'll take at it, tried to brake it up into smaller units of code to make it easier to work through. If I had enough time this could be further refined but then the readability goes south ;-)
Tried to avoid using TypeScript and to keep it as ECMAScript 5 friendly as possible. (Sorry about the messy formatting)
let ar100 = [1,1,1,1,1];
let ar25 = [1,12,23,5,2];
/**
* Calculate the lack of difference between two values (ie consistency)
* #param {number} valA
* #param {number} valB
* #returns {number} The consistency as a decimal
* where 1 is '100% consistent'
* and 0.5 is '50% consistent'
*/
var calcConsistency = function( valA, valB) {
let diff = Math.abs(valA - valB);
let consistency = (valA - diff) / valA;
// assumption: you can't be less than zero consistent
return consistency < 0 ? 0 : consistency;
}
/**
* A predicate used by the map operation in 'overallConsistency'
* #param {*} val
* #param {*} index
* #param {*} values
* #return {number} the average consistency of the current 'val' to the other 'values'
*/
var mapEachConsistency = function(val, index, values) {
let predicateGetOnlyOthers = function(currentValue, othersIndex) {
return index !== othersIndex;
};
let others = values.filter(predicateGetOnlyOthers);
const otherCount = others.length;
let totalConsistency = others.reduce(function(previousValue, currentValue) {
return previousValue + calcConsistency(val, currentValue);
});
return (totalConsistency / otherCount);
}
/**
* Calculate the overall average consistency of an array of numbers
* #param {Array<number>} arrayOfValues
* #return {number} The average consistency score as percentage
*/
var overallConsistency = function(arrayOfValues) {
let consists = arrayOfValues.map(mapEachConsistency);
let sumTotal = function(previous, current){ return previous + current; };
let avgAnswer = consists.reduce(sumTotal);
return (avgAnswer / consists.length) * 100;
};
// Here's using it to see the results
var answer = overallConsistency(ar100);
console.log(`Consistency: ${answer.toFixed(3)}% (fixed to 3 dicimal place)`);
answer = overallConsistency(ar25);
console.log(`Consistency: ${answer.toFixed(3)}% (fixed to 3 dicimal place)`);

How to get Row & Column values from A1Notation

Writing scripts for Google Spreadsheets can be difficult sometimes, because the Google Spreadsheet methods that take row and column numbers use 1-based indexing, while Javascript arrays use 0-based.
In this example, cell A2 has a row == 2 and column == 1. The SpreadsheetApp methods reverse column & row from those in A1Notation, so these two ranges are equivalent:
var range1 = sheet.getRange("A2");
var range2 = sheet.getRange(2, 1);
Once I read the contents of a sheet into an array, things are different again.
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var data = sheet.getDataRange().getValues();
After that, the value that was in cell A2 in my spreadsheet is in data[1][0]. The row & column are in the same order as the SpreadsheetApp API, but each is 1 less.
The answers to lots of questions here (example) have boiled down to mismatching of these different forms of indexing. Code that is full of row+1 and col-1 statements can be hard to debug.
Finally: If I know the reference for a cell in A1Notation, say AZ342, how can I find out the correct index values correspond to that cell in the 2D array, data, obtained from the full Data Range?
Obviously, you can just be very careful about keeping track of the places where you're using either type of indexing, and you'll be fine.
But it would be easier to do something like this:
var importantCell = "AZ342";
var cellIndexConverted = cellA1ToIndex( importantCell );
var data[cellIndexConverted.row][cellIndexConverted.col] = "Some new value";
ConvertA1.gs
Here are three helper functions to simplify conversion from A1Notation.
These helper functions are also available as a gist.
/**
* Convert a cell reference from A1Notation to 0-based indices (for arrays)
* or 1-based indices (for Spreadsheet Service methods).
*
* #param {String} cellA1 Cell reference to be converted.
* #param {Number} index (optional, default 0) Indicate 0 or 1 indexing
*
* #return {object} {row,col}, both 0-based array indices.
*
* #throws Error if invalid parameter
*/
function cellA1ToIndex( cellA1, index ) {
// Ensure index is (default) 0 or 1, no other values accepted.
index = index || 0;
index = (index == 0) ? 0 : 1;
// Use regex match to find column & row references.
// Must start with letters, end with numbers.
// This regex still allows induhviduals to provide illegal strings like "AB.#%123"
var match = cellA1.match(/(^[A-Z]+)|([0-9]+$)/gm);
if (match.length != 2) throw new Error( "Invalid cell reference" );
var colA1 = match[0];
var rowA1 = match[1];
return { row: rowA1ToIndex( rowA1, index ),
col: colA1ToIndex( colA1, index ) };
}
/**
* Return a 0-based array index corresponding to a spreadsheet column
* label, as in A1 notation.
*
* #param {String} colA1 Column label to be converted.
*
* #return {Number} 0-based array index.
* #param {Number} index (optional, default 0) Indicate 0 or 1 indexing
*
* #throws Error if invalid parameter
*/
function colA1ToIndex( colA1, index ) {
if (typeof colA1 !== 'string' || colA1.length > 2)
throw new Error( "Expected column label." );
// Ensure index is (default) 0 or 1, no other values accepted.
index = index || 0;
index = (index == 0) ? 0 : 1;
var A = "A".charCodeAt(0);
var number = colA1.charCodeAt(colA1.length-1) - A;
if (colA1.length == 2) {
number += 26 * (colA1.charCodeAt(0) - A + 1);
}
return number + index;
}
/**
* Return a 0-based array index corresponding to a spreadsheet row
* number, as in A1 notation. Almost pointless, really, but maintains
* symmetry with colA1ToIndex().
*
* #param {Number} rowA1 Row number to be converted.
* #param {Number} index (optional, default 0) Indicate 0 or 1 indexing
*
* #return {Number} 0-based array index.
*/
function rowA1ToIndex( rowA1, index ) {
// Ensure index is (default) 0 or 1, no other values accepted.
index = index || 0;
index = (index == 0) ? 0 : 1;
return rowA1 - 1 + index;
}
I wanted to post another solution since I usually think about converting strings using a loop rather than checking its length.
function convertSheetNotation(a1_notation) {
const match = a1_notation.match(/(^[A-Z]+)|([0-9]+$)/gm);
if (match.length !== 2) {
throw new Error('The given value was invalid. Cannot convert Google Sheet A1 notation to indexes');
}
const column_notation = match[0];
const row_notation = match[1];
const column = convertColumnNotationToIndex(column_notation);
const row = convertRowNotationToIndex(row_notation);
return [row, column];
}
function convertColumnNotationToIndex(a1_column_notation) {
const A = 'A'.charCodeAt(0);
let output = 0;
for (let i = 0; i < a1_column_notation.length; i++) {
const next_char = a1_column_notation.charAt(i);
const column_shift = 26 * i;
output += column_shift + (next_char.charCodeAt(0) - A);
}
return output;
}
function convertRowNotationToIndex(a1_row_notation) {
const num = parseInt(a1_row_notation, 10);
if (Number.isNaN(num)) {
throw new Error('The given value was not a valid number. Cannot convert Google Sheet row notation to index');
}
return num - 1;
}
Thank you to #Mogsdad as this is a small modification to your answer, although I believe my solution is less efficient.

Match IP with a range stored in an array

I am returning an IP and then comparing it from a range.
I am just looking at the US IP and if it falls in a range I am displaying a messge. I am getting the IP correctly but when I am trying to match it with the range I am getting a syntax error of unexpected range. How should I resolve this?
here is how my code looks like
$.getJSON("http://jsonip.com", function (data) {
var x = data.ip;
$('body').html(x);
var usRange = [3.0.0.0, 222.229.21.255];
if (x >= usRange[0] && x <= usRange[1]) {
alert('US');
} else alert('outside US');
});
Here is my fiddle
What the error means, you can't assign number with 4 decimal dots.
var usRange = [3.0.0.0, 222.229.21.255]; //Not possible
FYI: The IP address returned from the json is string, not a number.
So you approach won't work. Here check my approach,
1) Split the ip address based on . returned by $.getJSON
var x = data.ip.split('.'); // returns ["122", "164", "17", "211"]
2) Instead of using usRange array just do it with simple comparison operations.
3) You cannot compare strings with numbers, so convert those strings to numbers like
+x[0] //convert "122" to 122
Finally,
$.getJSON("http://jsonip.com", function (data) {
var x = data.ip.split('.');
if (+x[0] >= 3 && +x[0] <= 222) {
if (+x[1] >= 0 && +x[1] <= 229) {
if (+x[2] >= 0 && +x[2] <= 21) {
if (+x[3] >= 0 && +x[3] <= 255) {
alert("Within range");
}
}
}
} else {
alert("Is not within range");
}
});
JSFiddle
I decided to rewrite my answer here for the sake of a better method. The first method actually converts the IP addresses to integers using bit shifting and then compares the integer values. I've left the second answer as an option but I prefer the first.
Neither of these functions will validate your IP addresses!
Method 1: Bit Shifting
/**
* Checks if an IP address is within range of 2 other IP addresses
* #param {String} ip IP to validate
* #param {String} lowerBound The lower bound of the range
* #param {String} upperBound The upper bound of the range
* #return {Boolean} True or false
*/
function isWithinRange(ip, lowerBound, upperBound) {
// Put all IPs into one array for iterating and split all into their own
// array of segments
var ips = [ip.split('.'), lowerBound.split('.'), upperBound.split('.')];
// Convert all IPs to ints
for(var i = 0; i < ips.length; i++) {
// Typecast all segments of all ips to ints
for(var j = 0; j < ips[i].length; j++) {
ips[i][j] = parseInt(ips[i][j]);
}
// Bit shift each segment to make it easier to compare
ips[i] =
(ips[i][0] << 24) +
(ips[i][1] << 16) +
(ips[i][2] << 8) +
(ips[i][3]);
}
// Do comparisons
if(ips[0] >= ips[1] && ips[0] <= ips[2]) return true;
return false;
}
Method 2: Plain 'Ol Logic Mess
/**
* Checks if an IP address is within range of 2 other IP addresses
* #param {String} ip IP to validate
* #param {String} lowerBound The lower bound of the range
* #param {String} upperBound The upper bound of the range
* #return {Boolean} True or false
*/
function isWithinRange(ip, lowerBound, upperBound) {
// Save us some processing time if the IP equals either the lower bound or
// upper bound
if (ip === lowerBound || ip === upperBound) return true;
// Split IPs into arrays for iterations below. Use same variables since
// we won't need them as strings anymore and because someone will complain
// about wasting memory.
ip = ip.split('.');
lowerBound = lowerBound.split('.');
upperBound = upperBound.split('.');
// A nice, classic for loop iterating over each segment in the IP address
for (var i = 0; i < 4; i++) {
// We need those segments to be converted to ints or our comparisons
// will not work!
ip[i] = parseInt(ip[i]);
lowerBound[i] = parseInt(lowerBound[i]);
upperBound[i] = parseInt(upperBound[i]);
// If this is our first iteration, just make sure the first segment
// falls within or equal to the range values
if (i === 0) {
if (ip[i] < lowerBound[i] || ip[i] > upperBound[i]) {
return false;
}
}
// If the last segment was equal to the corresponding lower bound
// segment, make sure that the current segment is greater
if (ip[i - 1] === lowerBound[i - 1]) {
if (ip[i] < lowerBound[i]) return false;
}
// If the last segment was equal to the corresponding upper bound
// segment, make sure that the current segment is less than
if (ip[i - 1] === upperBound[i - 1]) {
if (ip[i] > upperBound[i]) return false;
}
}
return true;
}

Neural Network --- Back propagation algorithm error (In javascript!)

I have read quite a few back prop algorithms and i have no idea why mine is doing what it is doing.
Some notes before reading
No-hidden layer can "learn" all linear equations given a training set. Using 5 / 2 training it will even learn as accurate as 0.01% average error (fairly low)
When a hidden layer is used. The network will only output 2 values. One if both inputs are positive one if both inputs are negative.
The activation function of inputs -> hiddens -> (up to) outputs is f(x) = 1 / (1 + e^-x)
The activation function of outputs is linear (f(x) = x)
Error calculations
I believe this is where my possible error is at!
Outputs: E(k) = (target(k) - O(k).output) * f'(O(k).output) = (target - actual) * 1 linear activation fn gets 1 as derivative
Inputs and hiddens: E(j) = sum(w(kj) * E(k)) * f'(N(j).output) = sum(w(kj) * E(k) * N(j).output * (1 - N(j).output)
The full source code can be found here
http://www.github.com/primeagen/neural-js
The Source! Its in javascript!
Remember: Feedforward and output error seems to be correct since a non hidden layer network can learn any linear function and extrapolate well beyond its training set with a 0.01%. So i believe that is correct
Back prop error calculation
// Output layer
for (var i = 0; i < this._outputs.length; i++) {
var o = this._outputs[i];
o.error = targetOutputs[i] - o.output;
this._mse += o.error * o.error;
}
// Go through hidden layers
for (var cIdx = this._layers.length - 2; cIdx > 0; cIdx--) {
var curr = this._layers[cIdx];
var next = this._layers[cIdx + 1];
// Go through hidden neurons
for (var hN = 0, hLen = curr.length; hN < hLen; hN++) {
var h = curr[hN];
var sum = 0;
for (var nN = 0, nLen = next.length; nN < nLen; nN++) {
var n = next[nN];
sum += n.w[hN] * n.error;
}
h.error = sum * h.dActivationFn(h.output);
}
}
The activation function and its derivative
/**
* The logisticFunction function is 1 / (1 + e ^ (-x))
* #param x
*/
function logisticFunction(x) {
return 1 / (1 + Math.pow(Math.E, -x));
}
/**
* The derivative of the logistic function
* #param {Number} x
* #returns {Number}
*/
function dLogisticFunction(x) {
return x * (1 - x);
}
Neuron.dActivation = dLogisticFunction
My network just converges onto an answer (its random) and no matter the input (when positive) the value will not change when trained with 100+ data points...
Any idea?

Categories