I'm studing an algorithm problem and I did understand all the things except the lines that I marked up with comment into the code.
Note: It is not to solve the code. The code is working good. It is only to explain me about what is the marked lines' purposes.
let arr= [40, 50, 80, 20, 21, 35]
function qSort(arr) {
if(arr.length == 0){ // <-- These lines. I did NOT understand its purpose
return [];
}
var left = []
var right = []
var pivot = arr[0]
for(var i= 1; i<arr.length; i++) {
if(arr[i] < pivot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
return qSort(left).concat(pivot, qSort(right))
}
console.log(qSort(arr))
This code is working good, but When I comment these lines into the code, the script doesn't work and it cause an error message referencing a loop issue: Uncaught RangeError: Maximum call stack size exceeded
Does anybody explain it to me please? I would like to know what is this lines' purpose. Thanks
If the given array has a length of 0 (is empty), just return an empty array, because there is no sorting to be done.
Actually the line could be:
if(arr.length <= 1){
return arr;
}
since for 0 and 1 elements the's no sorting to be done.
This is related to the function being recursive (it calls itself) and therefor it needs a case, at wich it stops calling itself and return a value. That's called a recursion anchor.
This is called the base case of recursion, which ends the recursion. If you leave it away, qSort will call qSort will call qSort will call...
This line was written for optimization.
If there is no data in array you have nothing to sort.
Plus when you sort elements you are passing smaller and smaller chunks of base array to qSort function, so you have to finish qSort execution at one point.
So basically it tells the code "There is nothing to sort".
Related
I am a "new" developer into the foray of Web Development and I have come across an issue I was hoping that you fine people on Stack Overflow would be able to help me with. I have asked several Cadre and Instructors in my class and we are all stumped by it.
To start with I have decided to put all of my code on a Gitlab repo so if you want to look at the whole thing (or if you want to add to it let me know): Link to Github Repo. I fiqured you guys don't want the whole thing posted as a wall of text and rather some snip-its of what in the file I specifically. But it is relitively small file
I am useing simple JavaScript as well as Node.Js to be able to build a working calculator in the back end that I can use as a template for any other project I will need to work on in the future. For now I am trying to just get it working by imputing things via the console.
I have made a way for what is imputed in Node and to an imputArray var I have set up and the Array goes something like this:
[(command), (num1), (num2), (num3), ...]
I set up a switch function that runs a block of code based on what command was given (add, subtract, divide, etc..). As well as separating the command from the number and putting them inside another array.
The part I need some help with is with getting the block of code to work for what I want it to do. I have got it set up to run rather easily on two numbers but I want it to handle as many numbers as I want to throw at it. I tried various forms of for loops as well as forEach loops and I cant seem to get it working.
case 'divide':
for (i = 1; i < numArray.length; i++) { // If any number besides the first is 0 spit out this
if (numArray[i] === 0) {
consol.log("You canot divide by zero!");
}
else {
var previousTotal = numArray[0]; //Inital number in array
for (i = 1; i < numArray.length; i++) {
previousTotal = previousTotal / numArray[i]; // for each number in array divide to the previous number
}
}
result = previousTotal // Pushes end total to result
}
break;
I have gone through several different versions of the above code (such as using for loops instead) but this is pretty much what I ended up with. I'm sure there is an easier way and more sane way to do what I am trying to do, but if I knew how I wouldn't be here.
Essentially this is the ideal thing I want to do but I cant find a way to do it: I want to run a small block of code the index of the number array, minus one. In this case it is dividing the previous number by the next number in the array.
So it only runs if there are more then one in the array and it does the function to the previous number, or total from the last one in the array.
This is pretty much the only thing holding me back from finishing this so if someone can take the time to look at my crapy code and help it do what I want it to do that would be awesome.
Your code is reseting result each time the outer loop iterates so it will just equal what ever the last prev Total is. Basically every loop but the last is irrelevant. Do you want to add them to result? If so you want:
result += previousTotal
Or if you want an array of the answers you want:
result.push(reviousTotal)
Sorry not 100% what you want. Hope this helps!
You just need one loop, and you probably want to stop iterating if a 0 occurs:
result = numArray[0]; //no need for another variable
for (var i = 1; i < numArray.length; i++) { // declare variables!
if (numArray[i] === 0) {
console.log("You canot divide by zero!"); // typo...
break; // exit early
}
result = result / numArray[i];
}
For sure that can be also written a bit more elegantly:
const result = numArray.reduce((a, b) => a / b);
if(isNaN(result)) {
console.log("Can't divide by zero!");
} else {
console.log(`Result is ${result}`);
}
I assume you want the divide command to do ((num1/num2)/num3)/...
There are couple of issues in the code you posted, I will post a version that does the above. You can inspect and compare it your version to find your mistakes.
// divide, 10, 2, 5
case 'divide':
if (numArray.length < 2) {
console.log("no numbers in array")
break;
}
// previousTotal starts with 10
var previousTotal = numArray[1];
// start from the second number which is 2
for (i = 2; i < numArray.length; i++) {
if (numArray[i] === 0) {
console.log("You canot divide by zero!");
}
else {
previousTotal = previousTotal / numArray[i]; // for each number in array divide to the previous number
}
}
result = previousTotal;
// result will be (10/2)/5 = 1
break;
Here I am trying to implement merge-sort with javascript but I am getting an error maximum call stack size exceeded at array.slice
function mergeSort(arr) {
if(arr.length < 1) return arr;
let len = arr.length
let middle = Math.floor(len/2)
let left = arr.slice(0, middle)
let right = arr.slice(middle)
return merge(mergeSort(left), mergeSort(right))
}
Recursion never stops.
When the function will be called with an array of length 1, this array will be split in one array with length 0 (there the recursion stops) and another array with length 1. The function will be called again recursively with the second array. This will produce the same situation again.
This means, you must handle the situation where the array has the length 1 correctly (as already stated by Raphael, sorry I didn't see this before). You can simply return an array of length 1 because there is no need to sort.
I have an array of numbers with 64 indexes (it's canvas image data).
I want to know if my array contains only zero's or anything other than zero.
We can return a boolean upon the first encounter of any number greater than zero (even if the very last index is non-zero and all the others are zero, we should return true).
What is the most efficient way to determine this?
Of course, we could loop over our array (focus on the testImageData function):
// Setup
var imgData = {
data: new Array(64)
};
imgData.data.fill(0);
// Set last pixel to black
imgData.data[imgData.data.length - 1] = 255;
// The part in question...
function testImageData(img_data) {
var retval = false;
for (var i = 0; i < img_data.data.length; i++) {
if (img_data.data[i] > 0) {
retval = true;
break;
}
}
return retval;
}
var result = testImageData(imgData);
...but this could take a while if my array were bigger.
Is there a more efficient way to test if any index in the array is greater than zero?
I am open to answers using lodash, though I am not using lodash in this project. I would rather the answer be native JavaScript, either ES5 or ES6. I'm going to ignore any jQuery answers, just saying...
Update
I setup a test for various ways to check for a non-zero value in an array, and the results were interesting.
Here is the JSPerf Link
Note, the Array.some test was much slower than using for (index) and even for-in. The fastest, of course, was for(index) for(let i = 0; i < arr.length; i++)....
You should note that I also tested a Regex solution, just to see how it compared. If you run the tests, you will find that the Regex solution is much, much slower (not surprising), but still very interesting.
I would like to see if there is a solution that could be accomplished using bitwise operators. If you feel up to it, I would like to see your approach.
Your for loop is the fastest way on Chrome 64 with Windows 10.
I've tested against two other options, here is the link to the test so you can run them on your environment.
My results are:
// 10776 operations per second (the best)
for (let i = 0; i < arr.length; i++) {
if (arr[i] !== 0) {
break
}
}
// 4131 operations per second
for (const n of arr) {
if (n !== 0) {
break
}
}
// 821 operations per second (the worst)
arr.some(x => x)
There is no faster way than looping through every element in the array. logically in the worst case scenario the last pixel in your array is black, so you have to check all of them. The best algorithm therefore can only have a O(n) runtime. Best thing you can do is write a loop that breaks early upon finding a non-white pixel.
(Didn't find this Q while searching, but might be a matter of not knowing the terms for which to search)
Trying to mimic range() using code I found on SO (learning the language, so avoiding using ready-made functions in underscore.js), and I'm having trouble understanding why this will work:
var range = Array.apply(null,Array(3));
range = range.map(function (x, i) {return i;});
But this does not:
var range = Array.apply(null,Array(3));
range = range.map(function (x, i) {
console.log(range[i-1]);
return i;
});
< undefined
< undefined
< undefined
Ostensibly only difference is the console.log line, but why should that matter?
Thanks in advance!
The first line is creating an array of size 3, but the values will all be undefined. When you iterate it with map (to make a new range), you're logging by indexing; range[x - i] in the first loop is looking at range[undefined - 0] (becomes range[0]), and subsequent loops look at range[-1], etc. Of course they're undefined. Until the map completes, range has not been reassigned, so all you'll ever get is undefined. When the map completes though, with or without the log, range will be [0, 1, 2].
this.draw = function() {
console.log(this.buttonList.length);
for(a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
So I have this function within an object, and it's not working the way I expected it to. When I run it with the above console.log statements, it logs this on the console:
2
2 0
This seems to tell me that my for loop is not looping through every item on the array, and I've been scratching my head over why that would be for a quite a while now. Does anyone know why it's only performing the action for a = 0?
edit: I don't know if this makes a difference, but this function is called about 60 times every second.
Adding var would probably fix it :
this.draw = function() {
console.log(this.buttonList.length);
for(var a = 0; a < this.buttonList.length; a++) {
console.log(this.buttonList.length, a);
this.buttonList[a].draw();
}
};
There's very probably another point of your code where you change a. You should be careful with the variable declarations.
There are atleast three possibilities for the behavior:
a is overwritten (as per dystroys answer).
All elements in buttonList don't have a draw function.
this in the function definition of draw is an element in the buttonList.
The first two possibilities are easy to fix but the third one depends on what your intentions are, i.e. what do you wish to accomplish. To fix it we need more information.
Any one of the three possibilities (or combinations of the possibilities) could account for the behavior.
The first possibility is explained by dystroy.
The second possibility will stop excecution if an element doesn't have a draw function. In this case it seems to be the first element.
The third possibility will render in a stack overflow due to infinite recursion. The draw function is called over and over again just logging to console 2 then 2 0 until all the stack is consumed at which point the execution stops.