Why is the output of my JavaSript function undefined? [closed] - javascript

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
can anybody please hint me what is wrong in my Javascript function below?
I am finding the maximum multiple between two numbers.
When I write the code which is not inside the function in my testing window it works and it gives me what I need, but if I want to enclose it in my function the output is undefined. I believe that I miss something stupid but I have been solving that for several hours and I can not see it.
function maxMultiple(d, b){
const arr = [];
for (let i=b; i<=d; i+=b) { // i = i + b
arr.push(i)}
if (d>0 && b>0){
return arr.pop(); // does not work - undefined
} else {
return d; }
}
console.log(maxMultiple(7,100)); // Output is undefined
// it works....
/*
let b = 7;
const d = 100;
const arr = [];
for (let i=b; i<=d; i+=b) { // i = i + b
arr.push(i);
}
console.log(arr.pop()); //Output is 98
*/

Looks like you've interchanged the variables b and d. Just swap the parameters in the function signature, and you'll get what you expect.
The example you've shared will is working because you've used b as 7 and d as 100.
While in the actual code, the params you're passing are as follows:
b - 100, d - 7.
Therefore the for loop isn't executing even once, thereby logging undefined as mentioned by you.
Hope that helps!

Issue with this line for (let i = b; i <= d; i += b). In your program d is 7 and b is 100 so no element is ever pushed to array
function maxMultiple(d, b) {
const arr = [];
for (let i = b; i <= d; i += b) { // i = i + b
arr.push(i)
}
if (d > 0 && b > 0) {
return arr.pop(); // does not work - undefined
} else {
return d;
}
}
console.log(maxMultiple(7, 100));

Because 100 is less than 7. Array is empty. Nothing ever got pushed.
My guess is you got the two parameters in the wrong order.

function maxMultiple(d, b){
const arr = [];
for (let i=b; i<=d; i+=b) { // i = i + b
arr.push(i)
}
console.log(arr.length === 0); // array is empty here
if (d>0 && b>0){
let res; // cache result
// pop() on empty array always gives undefined
console.log([].pop() === (res = arr.pop()));
return res; // does not work - undefined
} else {
return d;
}
}
console.log(maxMultiple(7,100)); // Output is undefined
http://instacode.dev/#CmZ1bmN0aW9uIG1heE11bHRpcGxlKGQsIGIpewogIGNvbnN0IGFyciA9IFtdOyAKICBmb3IgKGxldCBpPWI7IGk8PWQ7IGkrPWIpIHsgLy8gaSA9IGkgKyBiCiAgICAgICBhcnIucHVzaChpKQogIH0KICAKICBjb25zb2xlLmxvZyhhcnIubGVuZ3RoID09PSAwKTsgLy8gYXJyYXkgaXMgZW1wdHkgaGVyZQogIAogIGlmIChkPjAgJiYgYj4wKXsKICAgIGxldCByZXM7IC8vIGNhY2hlIHJlc3VsdAogICAgLy8gcG9wKCkgb24gZW1wdHkgYXJyYXkgYWx3YXlzIGdpdmVzIHVuZGVmaW5lZAogICAgY29uc29sZS5sb2coW10ucG9wKCkgPT09IChyZXMgPSBhcnIucG9wKCkpKTsKICAgICByZXR1cm4gcmVzOyAvLyBkb2VzIG5vdCB3b3JrIC0gdW5kZWZpbmVkCiAgfSBlbHNlIHsgCiAgCXJldHVybiBkOwogIH0KIH0KCmNvbnNvbGUubG9nKG1heE11bHRpcGxlKDcsMTAwKSk7ICAvLyBPdXRwdXQgaXMgdW5kZWZpbmVkCg==

Related

Two sum algorithm: my solution returns undefined but prints the expected output [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 2 years ago.
Improve this question
I need some help before I go crazy because this does NOT make sense to me. So I would really appreciate it if someone can get me out of this hole.
This is the problem:
Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target. You may assume that each input would have exactly one solution, and you may not use the same element twice. You can return the answer in any order.
This is my code:
let numsCopy = [];
// new array to push the numbers index
let arrayResult = []
let currentNumberIndex = 0
var twoSum = function(nums, target) {
console.log('inside arrow function',nums, target);
// Copy the array
numsCopy = nums.slice(0)
// return fHelper(nums, target)
// let test = () => fHelper(nums, target)
console.log(fHelper(nums, target));
};
function fHelper(nums, target){
console.log('inside fhelper',nums, target);
// exit condition
if (nums.length < 1) return
// grab the first element and mutate our nums
let currentNumber = nums.shift()
for (var i = 1; i < numsCopy.length; i++) {
// check if the current number plus number in the next position of the array
// equals the target we are going to push the index of these numbers to the
// arrayResult
console.log('i: ', i, ' == ', 'numsCopy.length:', numsCopy.length);
console.log('nums length is: ', nums.length);
console.log(`${currentNumber} + ${numsCopy[i]} equals target ${target}?`)
if (currentNumber + numsCopy[i] === target) {
console.log('yes');
arrayResult.push(currentNumberIndex)
arrayResult.push(i)
console.log(arrayResult, 'typeof', typeof arrayResult, 'is array? ',Array.isArray(arrayResult));
return arrayResult
}
console.log('no');
}
console.log('currentNumberIndex: ', currentNumberIndex);
currentNumberIndex++
// recursion. we call again the function
//array nums get shorter every time with the shift()
fHelper(nums, target)
}
// Hello after hours of reading and trying to figured out and understand why my solution in some cases is returning undefined.
// This is my code and I dont understand why is returning undefined
// case 1
// twoSum([2,7,11,15], 9) // Expected output = [0,1]
// case 2
twoSum([3,2,4], 6) // in this case return undefined. Expected output= [1,2]
// case 3
// twoSum([3,3], 6) // Expected output= [0,1]
// case 4
// twoSum([3,3,2,8], 10) // in this case returns undefined. Expected output= [2,3]
// case 5
// twoSum([3,2,3], 6) // Expected output= [0,2]
You need a return statement at the end of the function.
function fHelper(nums, target) {
// ...
return fHelper(nums, target); // <<<<<<<<<
}
let numsCopy = [];
// new array to push the numbers index
let arrayResult = []
let currentNumberIndex = 0
var twoSum = function(nums, target) {
console.log('inside arrow function',nums, target);
// Copy the array
numsCopy = nums.slice(0)
// return fHelper(nums, target)
// let test = () => fHelper(nums, target)
console.log(fHelper(nums, target));
};
function fHelper(nums, target){
console.log('inside fhelper',nums, target);
// exit condition
if (nums.length < 1) return
// grab the first element and mutate our nums
let currentNumber = nums.shift()
for (var i = 1; i < numsCopy.length; i++) {
// check if the current number plus number in the next position of the array
// equals the target we are going to push the index of these numbers to the
// arrayResult
console.log('i: ', i, ' == ', 'numsCopy.length:', numsCopy.length);
console.log('nums length is: ', nums.length);
console.log(`${currentNumber} + ${numsCopy[i]} equals target ${target}?`)
if (currentNumber + numsCopy[i] === target) {
console.log('yes');
arrayResult.push(currentNumberIndex)
arrayResult.push(i)
console.log(arrayResult, 'typeof', typeof arrayResult, 'is array? ',Array.isArray(arrayResult));
return arrayResult
}
console.log('no');
}
console.log('currentNumberIndex: ', currentNumberIndex);
currentNumberIndex++
// recursion. we call again the function
//array nums get shorter every time with the shift()
return fHelper(nums, target)
}
// Hello after hours of reading and trying to figured out and understand why my solution in some cases is returning undefined.
// This is my code and I dont understand why is returning undefined
// case 1
// twoSum([2,7,11,15], 9) // Expected output = [0,1]
// case 2
twoSum([3,2,4], 6) // in this case return undefined. Expected output= [1,2]
// case 3
// twoSum([3,3], 6) // Expected output= [0,1]
// case 4
// twoSum([3,3,2,8], 10) // in this case returns undefined. Expected output= [2,3]
// case 5
// twoSum([3,2,3], 6) // Expected output= [0,2]
.as-console-wrapper { max-height: 100% !important; top: 0; }

JavaScript coding problem called FizzBuzz [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to figure out what I am doing wrong with this problem. I seem to be missing something that is not allowing my code to work. I need to use a function to create an array that takes one number n, and that loops through an array from the numbers 1 - 16, while also replacing all the numbers divisible by 3 with the string 'fizz', and all divisible by 5 with the word 'buzz', and any number that is divisible by both must be replaced by the string 'fizzbuzz'.
I have gone over this several times but for some reason keep coming up with just an empty array for my result when it is logged to the console. I would greatly appreciate it if someone could give me some tips as to why my code isn't working so that I can understand the concept easier. Here is my code:
const results = [];
const fizzbuzz = (n) => {
var results = []
for (let n = 1; results.length < 16; n++) {
if (n % 3 === 0 && n % 5 === 0) {
results.push('FizzBuzz')
} else if (n % 3 === 0) {
results.push('fizz');
} else if (n % 5 === 0) {
results.push('buzz')
} else {
results.push(n)
}
}
return results
};
fizzbuzz(16);
console.log(results);
This is what it is supposed to come out to:
[1, 2, 'fizz', 4, 'buzz', 'fizz', 7, 8, 'fizz', 'buzz', 11, 'fizz', 13, 14, 'fizzbuzz', 16]
But this is what I keep getting as an answer:
[]
Your fizzbuzz function returns results, so just assign that to a variable and log it:
var results = fizzbuzz(16);
console.log(results);
You are playing with another results inside the function, and outside the function result will remain empty. If you remove the variable which is inside the function now every manipulation will be on the same variable.
const results = [];
const fizzbuzz = (num) => {
for(let n=1; n<num; n++){
if(n%3 === 0 && n % 5 === 0){
results.push('FizzBuzz')
}
else if(n % 3 === 0){
results.push('fizz');
}
else if(n % 5 === 0){
results.push('buzz')
}
else {
results.push(n)
}
}
};
fizzbuzz(16);
console.log(results);
Your first issue is that the results variable declared outside your function and the results variable declared inside your function are totally different variables. You only need to declare the variable in the function, then you can make a new variable to hold the function result:
const res = fizzbuzz(16);
console.log(res);
or even simpler:
console.log(fizzbuzz(16));
The second issue is in your for loop, you are reassigning n when you should be making a new variable (most commonly called i). You also use a static number (16) as your limit in the expression results.length < 16, when you should use the variable n:
for (let i = 0; results.length < n; i++) {
if (i % 3 === 0 && i % 5 === 0) {
results.push('FizzBuzz')
} else if (i % 3 === 0) {
results.push('fizz');
} else if (i % 5 === 0) {
results.push('buzz')
} else {
results.push(i)
}
}
Overall you are taking the correct approach, but you should review variables and for loops as you are using both a bit incorrectly.
There are two glaring issues with your code.
You define the variable results twice, one as a constant and one as var.
If you remove the var results = [] definition, your code will work, as it's able to store the results through closures. Basically, the scope of your const results encapsulates the scope of your function, so your function will have access to const results = []
Your function isn't returning anything. This wouldn't be a problem if you were attempting to store the results via closures, but looking at your code, that wasn't your intention. What you should've done is store the results in a variable, as
const results = fizzbuzz(16)
This is my FizzBuzz implementation that uses Array.from() to generate an array with the fizz/buzz/number according to the rules:
const fizzbuzz = length => Array.from({ length }, (_, i) => {
if (i % 3 === 0 && i % 5 === 0) return 'FizzBuzz';
if (i % 3 === 0) return 'fizz';
if (i % 5 === 0) return 'buzz';
return i;
})
const results = fizzbuzz(16); // assign the return value of the function to results
console.log(results);

Why does my code work in one environment, but not in another?

I'm doing a kata on Codewars. I'm supposed to write a function that returns the index of which number, is not like the others, in evenness(i.e. [1, 2, 4] should return 0). I believe I have a solution, and it proves true when copy/pasting the code, and console.logging on freecodecamps live server, however, when i try to run the code where it is written, it only passes one test. What is going wrong here?
I've tried testing with console.logs, and my solution holds. I know I could just use filter to solve the problem, but i wan't to practice fundamentals.
let odd = [];
let even = [];
function isEven(num) {
if (num % 2 === 0) {
return true;
} else {
return false;
}
}
function iqTest(numbers) {
let nums = numbers.split(' ').map(function(item) {
return parseInt(item, 10);
})
for (let i in nums) {
if (isEven(nums[i])) {
even.push(nums[i])
} else {
odd.push(nums[i])
}
}
if (even.length > odd.length) {
return nums.indexOf(odd[0]) + 1;
} else {
return nums.indexOf(even[0]) + 1;
}
}
The function should accept a string of numbers, one of which will not be either even or odd, then return the index of that number + 1.
You could take the in comments mentioned approach and search for at least one odd and one even and one additional item, at least three items and exit early if this combination is found.
No need to convert the values in advance, because the value get converted to number by using the remainder operator of isEven function.
For a faster return value store the index instead of the value and omit a later indexOf seach.
function isEven(i) { return i % 2 === 0; }
function iqTest(numbers) {
var even = [], odd = [], values = numbers.split(' ');
for (let i = 0; i < values.length; i++) {
(isEven(values[i]) ? even : odd).push(i);
if (even.length && odd.length && even.length + odd.length > 2)
return (even.length < odd.length ? even : odd)[0] + 1;
}
}
console.log(iqTest("1 2 4")); // 1
console.log(iqTest("2 4 7 8 10")) // 3
console.log(iqTest("1 2 1 1")); // 2

Codewars problem 'Happy numbers' how can i make some changes on my code to make it works?

I am working Codewars problem' Happy Numbers ' here is the link https://www.codewars.com/kata/happy-numbers-5/train/javascript Here is the problem, when I am running the code when n > 98 the maximum call stack size is reached. How can I make some changes on my code to fix this problem?
function happyNumbers(x){
var res = [];
for (let i = 1; i <= x; i++){
var str = [];
if (helper(str,i)){res.push(i)}
}
return res
}
function helper(str,n){
var num = 0;
if (n === 1){return true}
if (str.indexOf(n) > -1){return false}
str.push(n);
if (n.toString().length === 1){num = Math.pow(n,2).toString()}
if (n.toString().length >= 2){
num = n.toString().split('')
.reduce((a,b) => Math.pow(a,2)+ Math.pow(b,2)).toString();
}
return helper(str,Number(num))
}
Maybe some more simplyfing would help by
using a Set for visited value to prevent circular loop which never ends (Memoization),
taking numerical values at all, only for splitting into single digits, a string is taken,
summing up by using a simple multiplication,
now some exit function:
check if sum is 1, exit the function with true,
check if sum is already visited and if so, exit with false,
return by calling the function again with sum and updated set visited with sum.
function happyNumbers(x, visited = new Set) {
var sum = 0, value;
for (value of String(x)) sum += value * value;
if (sum === 1) return true;
if (visited.has(sum)) return false;
return happyNumbers(sum, visited.add(sum));
}
console.log(happyNumbers(123));

Trying to write this in a more elegant way. Can I use a ternary in this function? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I was working on this practice problem, and solved it, but I want a more elegant way of writing this code:
// Usually when you buy something, you're asked whether your credit card number, phone number or answer to your most secret question is still correct. However, since someone could look over your shoulder, you don't want that shown on your screen. Instead, we mask it.
// Your task is to write a function maskify, which changes all but the last four characters into '#'.
const maskify = (cc) => {
let ccArray = Array.from(cc);
let length = cc.length;
let lastFour = cc.slice(-4);
let newArray = [];
if (length <= 4) {
return cc;
} else if (length > 4) {
let index = length - 4;
ccArray.splice(index, 4);
ccArray.forEach(n => {
newArray.push('#');
return newArray;
});
return newArray.concat(lastFour).join('');
}
}
console.log(maskify('4556364607935616'));
// ############5616
console.log(maskify('1'));
// 1
console.log(maskify('11111'));
// #1111
There are many different approaches:
function maskify(cc) {
return "#".repeat(Math.max(0, cc.length-4)) + cc.slice(-4);
}
function maskify(cc) {
return Array.from(cc, (char, index) =>
index < cc.length - 4 ? "#" : char
).join('')
}
function maskify(cc) {
return cc.replace(/.(?=.{4})/g, "#");
}
This might be among the easiest ways to achieve that goal:
const maskify = (cc) => {
return ("################################"+cc.slice(-4)).slice(-cc.length);
}
console.log(maskify('4556364607935616'));
console.log(maskify('1'));
console.log(maskify('11111'));
Just make sure the "################################" is long enough to cover all your use-cases.
To make it dynamic and work for any length of a string, it gets only slightly more complicated:
const maskify = (cc) => {
return ([...cc].map(x=>'#').join('')+cc.slice(-4)).slice(-cc.length);
}
console.log(maskify('4556364607935616'));
console.log(maskify('1'));
console.log(maskify('11111'));
You can also use a regular expression:
const maskify = (cc) => {
return (cc.replace(/./g,'#')+cc.slice(-4)).slice(-cc.length);
}
console.log(maskify('4556364607935616'));
console.log(maskify('1'));
console.log(maskify('11111'));
Generally speaking, I think your code is fine. Since "more elegant" is a little nebulous, I'll concern myself with 1) time complexity and 2) memory complexity
1) Time Complexity
Generally, you're fine here. No extra loops, and no intensive operations. There is a minor improvement to remove the final .join since that will have to loop over the final array.
2) Memory complexity
Some room for improvement here. Currently, the function creates a bunch of extra arrays. This likely won't be an issue for something as small as a credit card number, but could bite you if you applied a similar logic in a different situation.
Annotated original:
const maskify = (cc) => {
let ccArray = Array.from(cc); // Array 1
let length = cc.length;
let lastFour = cc.slice(-4); // Array 2
let newArray = []; // Array 3
if (length <= 4) {
return cc;
} else if (length > 4) {
let index = length - 4;
ccArray.splice(index, 4);
// Loop 1
ccArray.forEach(n => {
newArray.push('#');
return newArray;
});
// Loop 2
return newArray.concat(lastFour).join(''); // Array 4
}
}
Improved version:
const maskify = (cc) => {
let ccArray = Array.from(cc); // Array 1
let length = cc.length;
// Loop 1
let resultString = ccArray.reduce((result, original, index) => {
result += (index >= length - 4 ? original : '#');
}, "");
return resultString;
}
Array Reduce Documentation
As others have noted, there are many other ways to write this method. Since the question was specifically about how the existing code could be better, I tried to focus this answer on that.
Here's a way you can do it using destructuring assignment and single ternary expression
const maskify = ([ a = '', b = '', c = '', d = '', ...rest ]) =>
rest.length === 0
? a + b + c + d
: '#' + maskify ([ b, c, d, ...rest ])
console.log(maskify('4556364607935616'));
// ############5616
console.log(maskify('1'));
// 1
console.log(maskify('11111'));
// #1111
Destructuring creates intermediate values which can be avoided by using a secondary parameter, i, which represents the index of the current computation
const maskify = (str, i = 0) =>
4 + i >= str.length
? str.substr (i)
: '#' + maskify (str, i + 1)
console.log(maskify('4556364607935616'));
// ############5616
console.log(maskify('1'));
// 1
console.log(maskify('11111'));
// #1111
Now it's easy to make 4 an argument to our function as well
const maskify = (str, n = 4, i = 0) =>
n + i >= str.length
? str.substr (i)
: '#' + maskify (str, n, i + 1)
console.log(maskify('4556364607935616'));
// ############5616
console.log(maskify('4556364607935616', 6));
// ##########935616
console.log(maskify('1'));
// 1
console.log(maskify('11111', 10));
// 11111

Categories