The exercise is about identifying if all elements in an array are the same and return true if they are or false if they aren't. Below is the code & my logic behind writing the code.
function isUniform(array){
for(var i = array.length - 1; i>=0; i--){
if(array[i] !== array[i-1]){
return false;
}
}
return true;
}
Basically I want to start from the end of the array with the last element and check if its equal with the second-to-last element.If they're equal, the loop will subtract 1 from the "i" variable and the "if statement" will run again. The loop will stop when i reaches -1 and thats the point where every array element was checked and the loop should end, returning true. What am I doing / thinking wrong?
Thanks!
When i becomes 0, you are comparing arr[0] with arr[-1] which is wrong. Your checking condition should be i > 0.
The very last time it run, i is 0, so you're comparing array[0] with array[-1] which is incorrect. Your Boolean condition should be i > 0 so you avoid this issue:
function isUniform(array){
for(var i = array.length - 1; i > 0; i--){
if(array[i] !== array[i-1]){
return false;
}
}
return true;
}
You can use every method for a simplified solution.
const allEqual = arr => arr.every(x => arr[0] == x));
You could create a method that checks the array for your input using ArrayUtils.
public boolean contains(final int[] array, final int key) {
return ArrayUtils.contains(array, key);
}
Traveling so can't debug, but the last iteration of i will be 0 in your code and stop.
Related
I have been stuck on this problem for quite sometime. In addition to not using built in methods and the length property, we cannot use any loops either, which is a giveaway that this problem must be solved with recursion. I have tried this function but I am still stuck.
function getLength(string, length = 0){
if (string[0] === undefined) {return length};
length++;
return getLength(length);
}
console.log(getLength("hello"))
// expected answer: 5
You’re very close.
function getLength(string, length = 0){
if (string[length] === undefined) {return length};
length++;
return getLength(string, length);
}
console.log(getLength("hello"))
// expected answer: 5
You already figured the answer you just missed few parameters
function getLength(string, length = 0) {
if (string[length] === undefined) {
return length
};
length++;
return getLength(string, length);
}
console.log(getLength("hello"))
You can define the base case of the recursion which would terminate the recursion, as when either the string which is passed is empty/undefined/null or the the index at which you are in the recursive process has exceed the length of the given string in which case you would return 0.
Then call the function recursively by incrementing the index of the string and adding 1 in each recursive process till you hit the base condition:
function getLength(str, idx = 0) {
//base case
if (!str || !str[idx]) {
return 0;
}
return 1 + getLength(str, idx + 1);
}
console.log(getLength("hello"));
In the for loop: counter < (x.lenght) is spelled wrong, but the function returns zero. When corrected to x.length the function returns the correct number of Bs, 3. 1) Why is zero being returned? 2) Why does javascript not catch this error? 3) For the future, anything I can do to make sure these types of errors are caught?
function countBs(x){
var lCounter = 0;
for (var counter = 0; counter < (x.lenght); counter++){
if((x.charAt(counter)) == "B"){
lCounter++;
}
}
return lCounter;
}
console.log(countBs("BCBDB"));
Accessing x.lenght is returning undefined causing the for loop to terminate immediately. Therefore the initial value of lCounter is returned.
You can check for the existence of a property in an object by using the in keyword like so:
if ( 'lenght' in x ) {
...
x.lenght is returning undefined. Comparison operators perform automatic type juggling, so undefined is converted to a number to perform the comparison, and it converts to NaN. Any comparison with NaN returns false, so the loop ends.
Javascript doesn't catch this error because it uses loose typing, automatically converting types as needed in most cases.
There's no easy way to ensure that typos like this are caught. A good IDE might be able to detect it if you provide good type comments.
JavaScript does all kind of crazy coversions, instead of throwing an error: https://www.w3schools.com/js/js_type_conversion.asp
'undefined' in particular becomes NaN when necessary (very last line of the very last table), which results in 'false' when compared to a number (regardless of <, >, <=, >=, == or !=, they all fail, NaN does not even equal to itself).
If you want to catch or log an error to make sure your variable property is defined. Please see code below:
function countBs(x){
var lCounter = 0;
if(typeof x.lenght == 'undefined')
{
console.log('Undefined poperty lenght on variable x');
return 'Error catch';
}
for (var counter = 0; counter < (x.lenght); counter++){
if((x.charAt(counter)) == "B"){
lCounter++;
}
}
return lCounter;
}
console.log(countBs("BCBDB"));
To catch this particular error, set lCounter to -1 instead of 0.
That will ensure that the loop will run at least once if the for condition is correct.
You can return (or throw) an error if the loop isn't entered.
Otherwise, return lCounter + 1 to account for the initialization of -1.
function countBs(x) {
var lCounter = -1;
for (var counter = 0; counter < (x.lenght); counter++) {
if((x.charAt(counter)) == "B") {
lCounter++;
}
}
if(lCounter == -1) {
return 'Error';
} else {
return lCounter + 1;
}
}
I am in the midst of completing some JavaScript algorithmic challenges and I had to factorialize a number as part of one of them. After searching through stack and other places I entered a correct code block:
function factorialize(num) {
if(num === 0) {
return 1;
}
if(num < 0 ) {
return undefined;
}
for(var i = num; --i; ) {
num *= i;
}
return num;
}
factorialize(5);
It it returns a correct result. What I am struggling to understand however is why the for loop doesn't have a second statement, and why it can run for ever? I have an inkling it's because as soon as i value is 0, any subsequent negative number that is generated will be multiplied by 0 and so only the integer numbers will form the result. But why does the function return a valid number, if the loop is still running to -infinity and hasn't been told to stop when reaching a certain value?
the second part of your for loop is the Condition:
An expression to be evaluated before each loop iteration. If this expression evaluates to true, statement is executed. This conditional test is optional. If omitted, the condition always evaluates to true. If the expression evaluates to false, execution skips to the first expression following the for construct.
Once --i reaches 0, it evaluates to false (falsey) and the for "exits"
adding a console.log(i) to your for loop will help demonstrate that
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for
All elements in a for-loop's expression are optional.
The second part of the for-loop is used to express the for-loop's condition. The condition is evaluated on every iteration, and when it evaluates to false, the loop is exited.
In this case, that second part that expresses the condition is --i. This means that on every iteration, i will be decremented by 1, until it finally reaches zero (0). Since 0 is considered to be a falsey value in Javascript, the loop exits.
for (a; b; c)
is a direct equivalent to
a;
while (b) {
c;
}
You're mistaken here because you seem to think that c is what determines the end of the loop, but b actually is. You can omit the third loop statement if you don't need it (as well as the first one).
Here, your loop is equivalent to:
var i = num;
while (--i) {
num *= i;
}
while (--i) does two things:
Decrement i (before anything else)
Check that i != 0 (this is the actual loop condition).
If it was i--, note that the operations would be done in the opposite order.
If you find the code hard to read, you can also write it this way for the same results:
for (var i = num - 1; i != 0; i--) {
num *= i;
}
Normally you would have :
for(var i = 0; i < num; i++)
the second statement is a boolean continuation expression.
So when you have
for(var i = num; i--;)
The second is still a boolean continuation expression and when i get to 0 it evaluated to false.
function mutation(arr) {
var tester = arr[1].split('');
for (var i = 0; i < tester.length; i ++) {
if (!arr[0].indexOf(tester[i])) return false;
}
return true;
}
mutation(["hello", "hey"]);
Here I should return true if the string in the first element of the array contains all of the letters of the string in the second element of the array.
I do not see any problems with this code but it passes like only 90% of the tests and I do not know why. And I can not see a pattern there — what exact conditions should I meet to fail the test.
The indexOf() method returns the index within the calling String
object of the first occurrence of the specified value, starting the
search at fromIndex. Returns -1 if the value is not found.
String.prototype.indexOf() returns -1 if value was't found, that is why your statement doesn't work.
Change to:
if (arr[0].indexOf(tester[i]) < 0) return false;
This won't work because you are classing the first position (0 position) as not acceptable.
Your condition will only be true for values which aren't greater than 0, when 0 should also be valid.
Therefore change it so that it only returns false for values which are less than 0.
Change this line:
if (!arr[0].indexOf(tester[i])) return false;
To:
if (arr[0].indexOf(tester[i]) < 0) return false;
Things were really obvious — Upper/LowerCase() issue. This works now:
function mutation(arr) {
arr[0] = arr[0].toLowerCase();
arr[1] = arr[1].toLowerCase();
var tester = arr[1].split('');
for (var i = 0; i < tester.length; i ++) {
if (arr[0].indexOf(tester[i]) == -1) return false;
}
return true;
}
mutation(["hello", "hey"]);
And of course I have not noticed an obvious 0 position issue:
if (arr[0].indexOf(tester[i]) == -1) return false;
^ this is correct.
Thanks everyone!
I have two implements of function, that gets the last element of array.
function first(array) {
var length = array ? array.length : 0;
return length ? array[length - 1] : undefined;
}
function second(array) {
return array ? array[array.length - 1] : undefined;
}
And second function work with full array faster than first, but slowly with empty. Why and how I can fix it?
Benchmark with full array: http://jsperf.com/lodash-f-last/
Benchmark with empty array:
http://jsperf.com/lodash-f-last/2
If you want your code to be fast you should never ever read out of bounds: V8 deoptimizes the code that does that.
In you second function you do precisely that - you read out of bounds. Instead do the bounds check before reading:
function xlast(array) {
return (array && array.length > 0) ? array[array.length - 1]
: undefined;
}
To me it seems that second function is quicker with full array because you don't have to do the var length = array ? array.length : 0; like in the first function, which saves you an extra trinary condition.
With an empty array however, the second function is slower since you are forced to do an arr[-1] (because empty array still provides true inside if) which is a getter function and in the first function the condition is if (0) which is false and you simply return undefined.
As for your second question - how to fix it - I assume this will do the trick since it will save you the getter function:
function second(array) {
return array && array.length ? array[array.length - 1] : undefined;
}
In case of an empty array, it might be the cost of the array lookup, because your algorithms behave differently at zero length, note the control variable of the ? operator:
function first(array) {
var length = array ? array.length : 0;
return length ? array[length - 1] : undefined;
}
returns undefined for [] from evaluating the right side of the ?: construct, because 0 evaluates to false.
On the other hand,
function second(array) {
return array ? array[array.length - 1] : undefined;
}
returns undefined for [] from evaluating array[-1], because [] evaluates to true.
In case of the full array, the second algo is trivially simpler.