What is return -1 in javascript? - javascript

What is the return -1 on the third to last line of the below code? How does it work and what is its use?
function findElement(arr) {
let right_sum = 0, left_sum = 0;
for (let i = 1; i < arr.length; i++) {
right_sum += arr[i];
for (let i = 0, j = 1; j < arr.length; i++, j++) {
right_sum -= arr[j];
left_sum += arr[i];
if (left_sum === right_sum) {
return arr[i + 1];
}
}
return -1; // what is this?
}
}

It looks like the developer of that piece of code decided to return -1 if the for loop failed to return a value for error checking.
Its common for people to do these kinds of returns as it helps with error handling.

The return operator is used to return a value from inside a function, so the code return -1; makes the findElement function return the value -1 (negative 1) if the for loop doesn't work. This is useful for debugging. If the for loop works, then the function will return arr[i + 1].

It seems to be simulation of native arrays indexOf method. It returns -1 too, if no matches found.

Related

Logic is working fine in C++ but when same logic is Implemented in Javascript code leads to runtime error, why?

Input: Unordered consecutive integer array e.g. [6,4,3,1,2,5]
Output: Minimum number of swaps required to sort the array in ascending order [1,2,3,4,5,6]
For the same purpose the C++ implementation is:
int minimumSwaps(vector<int> arr) {
int i,c=0,n=arr.size();
for(i=0;i<n;i++)
{
if(arr[i]==(i+1))
continue;
swap(arr[i],arr[arr[i]-1]);
c++;
i--;
}
return c;
}
The C++ code is working fine!!
But when the same logic is implemented in JavaScript it is going into endless loop leading to runtime error.
JavaScript implementation:
function minimumSwaps(arr) {
let swaps=0,n=arr.length,i=0;
for(i=0; i<n; i++){
if(arr[i]===(i+1))
continue;
let temp= arr[i];
arr[i]= arr[arr[i]-1];
arr[arr[i]-1]=temp;
swaps++;
i--;
}
return swaps;
}
How to solve this issue and make the JavaScript code working?
function minimumSwaps(arr) {
let swaps = 0, n = arr.length, i = 0;
for (i = 0; i < n; i++) {
if (arr[i] === (i + 1)) {
let temp = arr[i];
arr[i] = arr[arr[i] - 1];
arr[arr[i] - 1] = temp;
swaps++;
}
}
return swaps;
}
Issue with swaping value between array's index. in c++ you used a method but in js you tried to write manually, but your written code is wrong
Instead use this code, it is optimized
function minimumSwaps(arr) {
let swaps=0,n=arr.length,j=0;
for(var i=0; i<n; i=j){
if(arr[i]!=(i+1)){
var temp = arr[i];
arr[i] = arr[temp-1];
arr[temp-1] = temp;
swaps++;
}else j++;
}
return swaps;
}
Or simply optimize your code
for(i=0; i<n; i++){
if(arr[i]===(i+1))
continue;
let temp= arr[i]; //temp is 6 as per your list
arr[i]= arr[arr[i]-1]; //just now you changed arr[i] into arr[arr[i]-1] , so it will become 5 as per your list,
arr[temp-1]=temp; //now temp-1 is 5 but if you use arr[arr[i]-1] it will become 4 bcoz arr[i] is 5 now
swaps++;
i--;
}
in your code the issue was,
first you set temp to arr[i] and arr[i] to arr[arr[i]-1]
so next time when you call arr[arr[i]-1] it become arr[arr[arr[i]-1]-1 as you previously set arr[i] as arr[arr[i]-1]

Codewars Javascript Problem- my code with a double for loop times out

I'm trying to solve a problem on Codewars which involves seeing if one string includes all the letters in a second string. I think I've found a decent solution, but my code times out (12000ms) and I can't figure out why. Could anyone shed some light on this issue?
function scramble(str1, str2) {
let i;
let j;
let x = str2.split();
for (i = 0; i < str1.length; i++) {
for (j = 0; j < str2.length; j++) {
if (str1[i] == str2[j]) {
x.splice(j, 1);
j--;
}
}
}
if (x.length == 0) {
return true;
} else {
return false;
}
}
If your strings have sizes N and M then your algorithm is O(N*M). You can get O(NlogN + MlogM) by sorting both strings and then do a simple comparison. But you can do even better and get O(N+M) by counting the letters in one string and then see if they are present in the other. E.g. something like this:
function scramble(str1, str2) {
let count = {}
for (const c of str1) {
if (!count[c])
count[c] = 1
else
count[c]++
}
for (const c of str2) {
if (!(c in count))
return false
count[c]--
}
for (let k in count) {
if (count.hasOwnProperty(k) && count[k] !== 0)
return false
}
return true
}
You created an infinite loop by both incrementing and decrementing j. The value of j gets stuck whenever str1[i] == str2[j]
Reducing your code snippet to the simplest form would look something like this:
for (j = 0; j < 10; j++) {
j--;
console.log(j) // always -1
}
You're adjusting x but then referring to str2 as if it has been changed. Because you never adjust str2, you're always comparing the same two letters, so you get stuck in a loop. That's one problem. Then, your question's wording suggests that we're checking if every letter in str2 is in str1, but you're going through every letter in str1 and checking it against str2. str1 should be the inner loop.
function scramble(str1, str2) {
var x = str2.split("");
for (var i = 0; i < x.length; i++) {
for (var j = 0; j < str1.length; j++) {
if (str1[j] == x[i]) {
x.splice(i--, 1);
}
}
}
return x.length === 0;
}
console.log(scramble("dirty rooms", "dormitory"));
console.log(scramble("cat", "dog"));
Because x.length === 0 is already a boolean value, you can just return that. No need for the if statements there. The triple equals checks the variable's type and value, and double equals only checks value. I tend to always use triple when I'm checking against 0 and 1 because you don't want unintended consequences like this:
console.log(false == 0, true == 1);
console.log(false === 0, true === 1);
Also, because i-- means "i = i - 1 after execution", you can put that directly in your call to splice, and it won't execute until after splice is finished. --i, on the other hand, would be evaluated before execution.
This is all great, but using indexOf is a simpler solution:
function scramble(str1, str2) {
for (let i = 0; i < str2.length; i++) {
if (str1.indexOf(str2[i]) == -1) return false;
}
return true;
}
console.log(scramble("forty five", "over fifty"));
console.log(scramble("cat", "dog"));

What's the problem with this implementation of selection sort?

I am learning selection sort.
I am getting the correct output for some values, but not for all the values, don't know why??
Please find below code snippet:
function selectionSortRecursion(arr,p){
if( arr.length === 1){
return p;
}
min=arr[0];
for(var i =0;i<arr.length;i++){
if (arr[i]<min){
min = arr[i];
var minIdx=i;
}
}
temp=arr[0];
arr[0]=arr[minIdx];
arr[minIdx]=temp;
p.push(arr.shift());
return selectionSortRecursion(arr,p);
}
console.log(selectionSortRecursion([2,3,5,-3,20,0,2,6,-23],[]));
The problem is that the variable minIdx is not declared unless the body of the if statement inside the loop is executed. If the minimum element is at index 0, then arr[i] < min is never true and minIdx is undefined.
To solve it, write var minIdx = 0; before the loop, since min is initialised as the value at index 0. A couple of your other variables should be declared with var, too:
function selectionSortRecursion(arr, p) {
if(arr.length === 0) {
return p;
}
var min = arr[0];
var minIdx = 0;
for(var i = 1; i < arr.length; i++) {
if (arr[i] < min) {
min = arr[i];
minIdx = i;
}
}
var temp = arr[0];
arr[0] = arr[minIdx];
arr[minIdx] = temp;
p.push(arr.shift());
return selectionSortRecursion(arr, p);
}
Note that I've also changed the loop variable i to start at 1, since there's no need to compare index 0 with itself; and the base case of the recursion should be when arr.length is 0, not 1, to avoid losing the last element.

Recursive Return Statement

This is a program that I have wrote to solve a problem. Check if there exists a sum of elements that equal to the maximum number in the array, return true if so, false otherwise.
var found = "false";
var max;
function ArrayAdditionI(array) {
max = Math.max.apply(null,array);
var p = array.indexOf(max);
array.splice(p,1);
array.sort(function(a, b){return a-b;});
found = findSum(array, 0, 0);
return found;
}
function findSum(array, sum, startIndex){
for(var i = startIndex; i < array.length ; i++){
sum += array[i];
if(sum === max){
found = "true";
break;
}else if(sum > max){
break;
}
if(i+2 < array.length && sum < max){
findSum(array, sum, i+2);
}
}
if(startIndex < array.length && sum !== max){
return findSum(array, 0, startIndex+1);
}
return found;
}
ArrayAdditionI(readline());
I had to use global variable, found, to indicate where a sum has been found or not. The return statement always returned undefined.
Also, if I use a return statement in the following if statement, the code does not work properly.
if(i+2 < array.length && sum < max){
return findSum(array, sum, i+2);
}
This is not the optimal solution to the problem, but this is the version I got working.
My question is Why am I getting undefined if I use return statement within the if statement. Also, I tried not using global and use return true if sum === max and at the very end return false, it always returns false or undefined.
-- UPDATE 2: Code with error results --
function ArrayAdditionI(array) {
var max = Math.max.apply(null,array);
//remove max element from array
var p = array.indexOf(max);
array.splice(p,1);
//sort array
array.sort(function(a, b){return a-b;});
//call find sum function
return findSum(array, 0, 0, max);
}
function findSum(array, sum, startIndex){
for(var i = startIndex; i < array.length ; i++){
sum += array[i];
if(sum === max){
return true;
}else if(sum > max){
break;
}
if(i+2 < array.length && sum < max){
**return** findSum(array, sum, i+2, max);
}
}
if(startIndex < array.length && sum !== max){
return findSum(array, 0, startIndex+1, max);
}
return false;
}
// calling the first function
ArrayAdditionI([ 7, 2,90, 31, 50 ]);
The start of the program is this call: ArrayAdditionI([ 7, 2,90, 31, 50 ]);
The return should be true.
Also, ArrayAdditionI([ 1,2,3,4 ]); is true.
However, ArrayAdditionI([ 1,2,3,100 ]); is false.
The return statement between ** **, when removed the code works, otherwise I either get false or undefined. I do not understand this part! Why does removing the return solves the problem, I thought every recursive call must be proceeded with a return statement.
Is the problem maybe due to multiple calls ? Am I using recursion in the improper way?
There are a few mistakes on your code that could lead to the error.
T.J. Crowder already said, use actual booleans instead of a string.
The found variable isn't defined inside your findSum function. That makes JavaScript assume you're setting a global variable.
Add var found = false; as the very first line of your findSum function.
Inside the last if inside your for there are a call to the findSum function but it's not returning it's value nor assigning it to the found variable.
Fix those and update your question with the results.
The following function should give you a true or false answer as to whether or not any combination of values inside an array produces the max figure.
var a = [
1, 1, 1, 1, 1, 1,
1, 1, 1, 9
]
var b = [1,1,1,5]
function MembersHoldMaxSum(arr) {
var i, r = false, index, max = Math.max.apply(null, arr), index;
for (i = 0; i <= arr.length - 1; i++) {
for (index = 0; index <= arr.length - 1; index++) {
var new_arr = [], ct;
for (ct = 0; ct <= arr.length - 1; ct++) {
if (index != ct) { new_arr.push(arr[ct]) }
}
while (new_arr.length != 1) {
var sum = 0, ct2 = 0;
for (ct2 = 0; ct2 <= new_arr.length - 1; ct2++) {
sum += new_arr[ct2];
}
if (sum == max) { return true }
new_arr.pop()
}
}
}
return r
}
var returns_true = MembersHoldMaxSum(a);
var returns_false = MembersHoldMaxSum(b);

Implementing Insert Function

I am currently working through Khan Academy's algorithm course, which uses JS to teach fundamental algorithms. I am currently in the process of implementing an insertion sort, but have found a problem.
We are writing a function which takes in an array, index to start from and value, in order to insert a number in the correct ordered position. I have written said function here:
var insert = function(array, rightIndex, value) {
for (var i = rightIndex; array[i] >= value; i--) {
array[i+1]=array[i];
array[i] = value;
}
return array;
};
This works fine, and performs as it should, however it does not pass KA's automated marking system. They give guidelines for the code and suggest it be done as such:
for(var ____ = _____; ____ >= ____; ____) {
array[____+1] = ____;
}
____;
Does anyone know how I could reiterate my code to conform to these standards?
I had a similar solution as you and didn't pass their automated test. If you look later at "Challenge: Implement insertion sort" they actually go ahead and implement the function for you:
var insert = function(array, rightIndex, value) {
for(var j = rightIndex; j >= 0 && array[j] > value; j--) {
array[j + 1] = array[j];
}
array[j + 1] = value;
};
As an aside, the reason you don't need to declare j before the for loop (to be used later) is because JavaScript doesn't have block scope (TIL): See here
From the challenge:
Although there are many ways to write this function, you should write it in a way that is consistent with the hint code.
It's strictly checking for this:
var ___;
for(___ = ___; ___; ___) {
array[___ + 1] = ___;
}
So even though these two alternates are correct:
while(array[rightIndex] > value && rightIndex >= 0) {
array[rightIndex + 1] = array[rightIndex];
rightIndex--;
}
array[rightIndex + 1] = value;
And especially this almost identical one (switched the middle statement in the for loop):
for(var i = rightIndex; array[i] > value && i >= 0; i--) {
array[i + 1] = array[i];
}
array[i + 1] = value;
This one is the answer:
for(var i = rightIndex; i >= 0 && array[i] > value; i--) {
array[i + 1] = array[i];
}
array[i + 1] = value;
Ironically, it doesn't care about the useless first variable in the hint...
var ___;
No need to return the array, as it is passed by reference. Just shift every element by 1 to the right. The last statement just inserts the value at the correct position.
var insert = function(array, rightIndex, value) {
for (var i = rightIndex; array[i] >= value; i--) {
array[i+1] = array[i];
}
array[rightIndex] = value;
};
Most of the answers posted here are correct. But It does not get us to next step in Khan Academy. It could be because Khan Academy expects a certain variable name, indent settings etc. I am not exactly sure why It does not get us to next step.
This code helped me go to next step:
var insert = function(array, rightIndex, value) {
for(var j = rightIndex;
j >= 0 && array[j] > value;
j--) {
array[j + 1] = array[j];
}
array[j + 1] = value;
};
Before I discovered this code, I used i as variable name instead of j, but it did not get me to next step. But this does.
This has worked:
var insert = function(array, rightIndex, value) {
var j = rightIndex;
for(var j = rightIndex; j >= 0 && array[j] > value; j--) {
array[j + 1] = array[j];
}
array[j + 1] = value;

Categories