Function to create new array producing undefined - javascript

I am trying to write a program that creates an array and populates it with a range of numbers. The function range's x, y, z variables correlates to the start number, the end number, and the number value of each step. My goal is produce an array with all the numbers between (and including) x and y that is created with each step. Here is the code:
let newarray = []
function range (x, y, z){
if (x === undefined || y === undefined || z === undefined || (x > y) || (z < 0)) {
return newarray; // returns empty array if x, y, or z is undefined, x is greater than y or z is a negative integer
}
else if (y > x) {
for (x; x < y; x = x += z) {
newarray.push(x); //pushes x into an array then adds z into x and loops until x exceeds y
}
}
else {
return newarray; //prints out new array
}
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));
right now it is producing undefined for all three numbers. My research suggests something about asynchronicity? I'm not sure what that means.

A few things are at play here:
newArray should be defined inside the function scope rather than as a global variable. Otherwise, subsequent calls to the function will keep appending onto the same array, which is likely not your intention (and if it was, there's array.concat() for that).
Your last else is unreachable, so the function will either return an empty array for input failing your validation or return undefined when control reaches the end of the function after populating the array in the else if block.
x = x += z is probably intended as x += z.
You should disallow z === 0 otherwise you'll wind up with an infinite loop.
Normal JS style is to camelCase variable names.
Additionally, I find it's easier to write positive conditionals than negative conditionals. In this case, enumerating what arguments are allowed seems cleanest. This approach enables you to only have one return statement and fewer conditional branches, mitigating potential confusion.
Here's a version that addresses these issues:
function range(x, y, z) {
const newArray = [];
if ([x, y, z].indexOf(undefined) < 0 && x < y && z > 0) {
for (; x < y; x += z) {
newArray.push(x);
}
}
return newArray;
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));

Note that the section where you check else if (y > x) does not have a return. When this condition is true, your function returns undefined. To fix the problem, just add return newarray; as the last line in the function. Then remove all other lines with return new array;.

The else block is not required as it will be unreachable and will
return undefined.
Corrected x = x + z from x = x += z.
The array declaration was outside, so every time the old data will be
appended with newer data from the for loop.
function range (x, y, z){
let newarray = [];
if (x === undefined || y === undefined || z === undefined || (x > y) || (z < 0)){
return newarray;
}
else if (y > x) {
for (x; x < y; x = x + z){
newarray.push(x);
}
}
return newarray;
}
console.log(range(0, 10, 2));
console.log(range(10, 30, 5));
console.log(range(-5, 2, 3));

Related

Determine if a number, n, is a power of some other number k. Return the exponent

Determine if a number, x, is a power of some other number y. Return the exponent. For example, for n = 9 and k = 3, return 2 because 3 to the power of 2 is 9. If n is not a power of k, return -1. I can't figure out how to return the exponent in this problem. Should I be using mod % ? Also, this problem requires a recursive solution.
function solution(x, y) {
if (x == 1)
return (y == 1);
let pow = 1;
while (pow < y)
pow = pow * x;
return solution(pow, y - 1);
};
console.log(solution(3, 9)); // should return 2 because 3 to the power of 2 is 9.
use % to get the remainder, you can determine whether the remainder is 0 to determine the subsequent operation, I did not use recursion, but also the real output of the correct result, you see if it meets your requirements
function solution(x, y) {
if (y % x !== 0 || x > y) return -1
if (x === y) return 1
let i = 0
while (y % x === 0) {
i++
y /= x
}
return i
}
console.log(solution(3, 9))

Find the Greatest Common Divisor

Here is the question.
Find the greatest common divisor of two positive integers. The integers can be large, so you need to find a clever solution.
The inputs x and y are always greater or equal to 1, so the greatest common divisor will always be an integer that is also greater or equal to 1.
Here is my solution.
function mygcd(x, y) {
//your code here
let gcd = [];
let lowestNum;
let bigestNum;
//detect the lowest and bigest numbers
if (x < y) {
lowestNum = x;
bigestNum = y;
} else if (x > y) {
lowestNum = y
bigestNum = x;
} else {
lowestNum = x
}
//check if the bigest num has a modolo == 0
//else loop the lowest num and push in the array
if (bigestNum % lowestNum === 0) {
return gcd += lowestNum;
} else {
let arrNum = []
for (let i = 1; i < lowestNum; i++) {
// console.log(i)
arrNum.push(i)
}
//loop the array backwards
for (i = arrNum.length - 1; i >= 1; i--) {
if (lowestNum % arrNum[i] === 0 && bigestNum % arrNum[i] === 0) {
console.log(arrNum[i])
if (gcd !== 0) {
return
} else {
// gcd += arrNum[i]
let vals = gcd.push(arrNum[i])
console.log(typeof(vals))
}
}
}
}
console.log(gcd)
return gcd[0];
}
console.log(mygcd(30, 12))
The above solution works for the test cases i tried it for, but the issue is that it returns the correct divisor and undefined.
This is what my logs look like
6
undefined
6
undefined
The test cases
test:
Log
6
expected undefined to equal 6
so it gets undefined instead of 6 or the correct divisor.
I also tired a different recursive approach below.
Note: This works well.
function mygcd(x, y) {
if (!x) return y
if (!y) return x
return mygcd(y, x % y)
}
console.log(mygcd(30, 12))
console.log(mygcd(8, 12))
But i am curious to understand why my original solution breaks. Any help would be really appreciated.
Thanks

Identical function leads to different outcomes in different languages

I wrote a function in javascript that is supposed to return the lowest prime number larger than x. Instead it get's caught in indefinite recursion.
function next_prime(x) {
if (x <= 1) {
return 2;
}
y = 2;
z = x + 1;
while(true) {
if (z % y == 0) {
z++;
y = 2;
continue;
}
if(y * y > z) {
return z;
}
y = next_prime(y);
}
}
I didn't understand what was wrong, so I implemented the same function in python, where it worked just fine.
def next_prime(x):
if x <= 1:
return 2
y = 2
z = x + 1
while True:
if z % y == 0:
z += 1
y = 2
continue
if y * y > z:
return z
y = next_prime(y)
I looked over both functions and I'm sure that they are identical, yet in python it works and in javascript it doesn't.
Allthough appreciated, I'm not necessarily looking for help with this specific problem, I'm more so interested in what is actually going on here.
I think the problem is that you are not declaring your variables correctly. In JavaScript, you have to use the keywords let and const - which stand for reassignable and not reassignable variables - when declaring a new variable. When using let in lines five and six, the function works just fine.
You should use strict mode to avoid this common mistake of javascript beginners.
your actual js code with 'use strict'; is rejected :
'use strict';
console.log( next_prime(7) ) // never run on strict mode, otherwise make an infinite loop
function next_prime(x) {
if (x <= 1) {
return 2;
}
y = 2;
z = x + 1;
while(true) {
if (z % y == 0) {
z++;
y = 2;
continue;
}
if(y * y > z) {
return z;
}
y = next_prime(y);
}
}
same code in correct javascript syntax :
'use strict';
console.log( next_prime(7) ) // -> 11
function next_prime(x)
{
if (x <= 1) return 2
;
let y = 2, z = x + 1 // declare y and z as locale
;
while(true)
{
if (z % y == 0)
{
z++;
y = 2;
continue;
}
if (y**2 > z) return z
;
y = next_prime(y);
}
}
explanation : your code is recursive, inside call will change y and z value on parent callers and make an infinite loop

If then logic with && ||

Can someone explain to me or point me to documentation as to why the following function doesn't work?
var x = 1;
var y = 2;
var z = 1;
function logicTest() {
if ((x && y && z) === 1) {
return true;
} else {
return false;
}
}
console.log(logicTest())
I know that I can type it out the long way as follows:
var x = 1;
var y = 2;
var z = 1;
function logicTest() {
if (x === 1 && y === 1 && z === 1) {
return true;
} else {
return false;
}
}
console.log(logicTest())
But I'm really trying to understand why the first doesn't work and also if there is a better way of typing the second if/then statement or if that is just the way it will always have to be.
Thanks!
The expression
((x && y && z) === 1)
first involves the evaluation of (x && y && z). To evaluate that, JavaScript tests, in sequence, the values of x, y, and z. If, left to right, one of those values when coerced to boolean is false, evaluation stops with that (uncoerced) value as the value of the whole thing. Otherwise, the value of that subexpression will be the value of z, because it's the last subexpression in the && sequence.
In this case, x, y, and z are all non-zero numbers, so the overall result will be 1, because z is 1.
What you seem to want to be able to do is test whether all of a set of subexpressions are equal to the same value. That, as you've found, can only be determined by explicit comparison. It's also something that could be done by creating a list and then using array functions to perform the tests, which would be useful when there are more than just three subexpressions to test.
Also, on a stylistic note:
function logicTest() {
if (x === 1 && y === 1 && z === 1) {
return true;
} else {
return false;
}
}
Performing tests with relational operators like === generates boolean values. It's more concise to take advantage of that:
function logicTest() {
return x === 1 && y === 1 && z === 1;
}

x >= x pattern in JavaScript

When reading source of D3.js I saw x >= x pattern. If it is for detecting NaNs among numbers, why not just isNaN(x) or x == x?
Source, where I encountered it:
d3.min = function(array, f) {
var i = -1, n = array.length, a, b;
if (arguments.length === 1) {
while (++i < n) if ((b = array[i]) != null && b >= b) {
a = b;
break;
}
while (++i < n) if ((b = array[i]) != null && a > b) a = b;
} else {
while (++i < n) if ((b = f.call(array, array[i], i)) != null && b >= b) {
a = b;
break;
}
while (++i < n) if ((b = f.call(array, array[i], i)) != null && a > b) a = b;
}
return a;
};
From my investigations, d3.min is supposed to work on any kind of orderable values, not only numbers. isNaN would only work numbers.
d3 was actually using == at some point. This commit introduced the x == x test:
Unlike Math.min and Math.max, it doesn't make sense to return negative or positive infinity for d3.min and d3.max; the D3 functions return the minimum value according to an arbitrary ordering, not by numeric value. Instead, the minimum or maximum of an empty array, or an array that contains only degenerate values, should always be undefined.
This commit changed x == x to x <= x (which was later again changed to x >= x):
In addition to NaN, which is not equal to itself, you can have objects that are not orderable due to defined valueOf functions which return NaN. For example:
var o = new Number(NaN);
Here, o == o is true, but o <= o is false. Therefore it was possible for d3.min, d3.max and d3.extent to observe these non-orderable values rather than ignore them as intended. The fix is to check !(o <= o) rather than o == o.
OK, I see that x >= x gives false for both NaN and undefined. (Unlike isNaN(x) or x == x.)
EDIT: While it is one of the use cases of x >= x, in this case (thx #Felix Kling for pointing this out) undefined is already being checked.

Categories