Re-usable while loop function isn't looping - javascript

Still a little new to javascript so this might be an easy fix but could anyone tell me why the following code does not work?
I am trying to create a reusable function that will increment from count to countTo in increments of countBy. I would like to vary those increments (either all evens, all odds, only numbers divisible by 5, etc). Right now it is just printing out -10 and not looping. Also it doesn't know count exists unless i make it global and I'm not sure why.
Thanks in advance!
EDIT: initialized count with count = 0, it works now. I'm still not sure why it doesn't just recognize the value of count when i pass it in as an argument though. Are they not the same "count"?
//count = incrementing variable
//countTo = final result
//countBy = how we should increment count
var count;
function looping(count, countTo, countBy) {
while(count <= countTo) {
console.log(count);
count = countBy(count);
}
}
console.log("-10 to 19");
var counting1 = looping(-10, 19, function () {
return count++;
});

Since this question is tagged with functional-programming I'll answer it using functional techniques.
Where you went wrong
var count;
function looping(count, countTo, countBy) {
// because you named a parameter `count`, you shadowed the external `count` variable
while(count <= countTo) {
console.log(count);
// this doesn't reassign outer count
// instead it reassigns local count and is discarded after function exits
count = countBy(count);
}
}
Functional programming advises against things like this tho anyway ā€“ and in some languages, it's outright impossible to do. External state is discouraged and variable reassignment is usually an indicator for problems. Let's start by adjusting how the code should work
var count; // no need for external state
var counting1 = looping(-10, 19, function (count) { // use local parameter
return count++; // ++ is a mutating function
return count + 1
});
Instead of relying upon external state, count, we will pass count into the function each loop. And rather than using count++, although it would work in JavaScript since numbers are already immutable, it's better to get in the habit of using non-mutating functions. Also count + 1 makes it clear that a mutation is not necessary here and things like count + 2 would work if we wanted to count by twos ā€“ or count * 2 if we wanted to double the counter each time, etc.
To make this work, it's actually quite easy. Below is a recursive function which continues looping until from is greater than to. Each loop will send the current counter value into the callback, f, which is expected to return the next value of the counter.
function looping (from, to, f) {
if (from > to)
return from
else
return looping (f (from), to, f)
}
looping (-3, 3, function (count) {
console.log (count)
return count + 1 // count by 1
})
// -3, -2, -1, 0, 1, 2, 3
// => 3
looping (-3, 3, function (count) {
console.log (count)
return count + 2 // count by 2
})
// -3, -1, 1, 3
// => 3
There's nothing wrong with using a while-loop, but it's important to keep any mutable state localized to the looping function. The important lesson here is that the usage of our function looks exactly the same and even tho the implementation changed, there are still no side effects.
function looping (from, to, f) {
while (from < to) from = f (from)
return from
}
looping (-3, 3, function (count) {
console.log (count)
return count + 1 // count by 1
})
// -3, -2, -1, 0, 1, 2, 3
// => 3
looping (-3, 3, function (count) {
console.log (count)
return count + 2 // count by 2
})
// -3, -1, 1, 3
// => 3

count doesn't have a value by the time you increment it, hence it becomes NaN.

You are making a simple function complex by using inline function call which is not correct. If question is about how to get this functionality, here is simple solution.
function looping(count, countTo, countBy) {
while(count <= countTo) {
console.log(count);
count += countBy;
}
}
console.log("-10 to 19");
var step = 2;
var counting1 = looping(-10, 19, step);

Related

Recursion better understanding

https://www.freecodecamp.org/learn/javascript-algorithms-and-data-structures/basic-javascript/use-recursion-to-create-a-countdown
We have defined a function called countdown with one parameter (n). The function should use recursion to return an array containing the integers n through 1 based on the n parameter. If the function is called with a number less than 1, the function should return an empty array. For example, calling this function with n = 5 should return the array [5, 4, 3, 2, 1]. Your function must use recursion by calling itself and must not use loops of any kind.
// Only change code below this line
function countdown(n){
if (n<1)
return [];
else{
const numbArray = countdown(n-1);
numbArray.push(n)
return numbArray;
}
}
console.log(countdown(5))
// Only change code above this line
comes out like [1 2 3 4 5] instead of [5 4 3 2 1]
I've been breaking my mind forever then I have completed it with the unshift method but felt like it wanted to me use push even though that sends data to the end of the stack
function countdown(max, currentN) {
if (currentN > max)
return [];
else if (currentN <= max) {
const numbArray = countdown(max, currentN + 1);
numbArray.push(currentN)
return numbArray;
}
}
console.log(countdown(5, 1))
// Only change code above this line
basically it just counts up to the end value given at start
else {
const arr = []
arr.push(n)
return arr.concat(countdown(n-1))
}
you can use this code replace, y question reason is y not understand recursion, try to break the point and watch the function execution step by step in the browser or vscode

How to find the count of repeated numbers in an given array and return the output as an object

I have been asked with this question in one of my recent interviews.
For a given array, say, Arr[2,2,4,3,4,2,3,2,4]
write a javascript function to return an object with the count of each number in the above array, like
countArr={2:4,3:2,4:3}
After a lot of google I have ended up with the below code which is returning the correct data.
var uniqueCount = [2, 2, 4, 3, 4, 2, 3, 2];
var count = {};
uniqueCount.forEach(function(i) {
count[i] = (count[i] || 0) + 1;
});
console.log(count);
As I said this works fine! Output: {2: 4, 3: 2, 4: 2}
Well, a code without proper understanding of whats happening in back ground means nothing for a developer :)
Can anyone please help me out to understand how this actually work?
The main work of creating an object with each of the unique array element's count
is happening in the following block:
uniqueCount.forEach(function(i) {
count[i] = (count[i] || 0) + 1;
});
Here we are iterating over each of the elements in the array like we do in a 'for loop'. I hope you are familiar with the working of a 'for loop'. Then, we are passing each element of the array in a function.
count[i] = (count[i] || 0) +1;
can be written as:
if(count[i]) {
count[i] = count[i] + 1;
} else {
count[i] = 1;
}
Hope that helps you to understand the code.
Ok, it's actually simple. Let's go step by step.
var count = {};
Declares a JS object. It's basically a key-value store. You can access the value of a key by writing count[key]. Then store or retrieve the value.
Consider this simple example:
var count = {}
count['ok'] = 3
console.log(count)
It outputs { ok: 3 }
Now replace 'ok' with a number, and you get the structure of the rest of the code : keys are added to the object for each number found in the array, or are incremented when they exists.
Let's continue with the code.
uniqueCount.forEach(function(i) {
// code here is called for each entry in the uniqueCount array, i being the current value.
});
And finally, the magic happens here:
count[i] = (count[i] || 0) + 1;
From left to right, it reads: assign to the i property of the count object a value that is it's current value or 0 if there is none, then add 1. So if the i number was already seen it takes the previous value and adds 1; if it wasn't seen, it takes 0 and adds one.
So when you console.log(count) you get the values for all of those properties.
The code uses an object as a map from number values to integer counts of their frequency.
1. var uniqueCount = [2, 2, 4, 3, 4, 2, 3, 2];
2. var count = {};
3. uniqueCount.forEach(function(i) {
4. count[i] = (count[i] || 0) + 1;
5. });
6. console.log(count);
Line 1: Declare variable uniqueCount and assign to it a new array of numbers.
Line 2: Declare variable count and assign to it a new, empty object.
Line 3: Run an anonymous function once for each number in uniqueCount.
Line 4: Assign to a property on count, named with the current number in the array: one plus the existing value of the property, or if the property does not already exist, zero.
Line 6: Print the final state of count.
The code would be clearer if the variable i in the anonymous function was named n (or something) because i (yes, I know it means "integer" here) usually means "index", and here, it is not the index.
Note that in JavaScript simply assigning a value to a property on an object will create that property if it does not already exist.
I assume there is only one line that confused you:
count[i] = (count[i] || 0) + 1; means
If there is already a count for digit i set count[i] to that value, otherwise set it to 0 (initialise it) then add 1 to whatever is in count[i] now
Can be rewritten like this to make it more understandable - note I changed the variable, array and object names
var array = [2, 2, 4, 3, 4, 2, 3, 2];
var uniqueCount = {};
array.forEach(function(digit) {
if (uniqueCount[digit]) uniqueCount[digit]++; // if counter for the digit exist, add 1
else uniqueCount[digit] = 1; // else initialise it to 1
});
console.log(uniqueCount);

JS: Finding unpaired elements in an array

I have the following question (this is not school -- just code site practice questions) and I can't see what my solution is missing.
A non-empty array A consisting of N integers is given. The array contains an odd number of elements, and each element of the array can be paired with another element that has the same value, except for one element that is left unpaired.
Assume that:
*N is an odd integer within the range [1..1,000,000];
*each element of array A is an integer within the range [1..1,000,000,000];
*all but one of the values in A occur an even number of times.
EX: A = [9,3,9,3,9,7,9]
Result: 7
The official solution is using the bitwise XOR operator :
function solution(A) {
var agg = 0;
for(var i=0; i<A.length; i++) {
agg ^= A[i];
}
return agg;
}
My first instinct was to keep track of the occurrences of each value in a Map lookup table and returning the key whose only value appeared once.
function solution(A) {
if (A.length < 1) {return 0}
let map = new Map();
let res = A[0]
for (var x = 0; x < A.length; x++) {
if (map.has(A[x])) {
map.set(A[x], map.get(A[x]) + 1)
} else {
map.set(A[x], 1)
}
}
for ([key,value] of map.entries()) {
if (value===1) {
res = key
}
}
return res;
}
I feel like I handled any edge cases but I'm still failing some tests and it's coming back with a 66% correct by the automated scorer.
You could use a Set and check if deletion deletes an item or not. If not, then add the value to the set.
function check(array) {
var s = new Set;
array.forEach(v => s.delete(v) || s.add(v));
return s.values().next().value;
}
console.log(check([9, 3, 9, 7, 3, 9, 9])); // 7
You're not accounting for cases like this:
[ 1, 1, 2, 2, 2 ] => the last 2 is left unpaired
So your condition should be if ( value % 2 ) instead of if ( value === 1 ).
I think also there is not much benefit to using a Map rather than just a plain object.
The official solution works due to the properties of the bitwise XOR (^), namely the fact that a ^ a == 0, a ^ 0 == a, and that the operation is commutative and associative. This means that any two equal elements in the array will cancel each other out to become zero, so all numbers appearing an even amount of times will be removed and only the number with an odd frequency will remain. The solution can be simplified using Array#reduce.
function findOdd(arr) {
return arr.reduce((a,c)=>a ^ c, 0);
}
You need not to make a count of each and traverse again, if you are sure that there will be exactly one number which will occur odd number of times. you can sum the array and do + when odd entry and - when even entry (to dismiss it back) and in the hash (map or object) you can just toggle for subsequent entry of each number.
Here is an example:
let inputArray1 = [10,20,30,10,50,20,20,70,20,70,50, 30,50], //50 -> 3 times
inputArray2 = [10,20,30,20,10], //30 -> 1 time
inputArray3 = [7,7,7,7,3,2,7,2,3,5,7]; //5 -> 1 time
let getOddOccuence = arr => {
let hash = {};
return arr.reduce((sum, n) => sum + ((hash[n] = !hash[n]) ? n : -n), 0);
}
console.log('Input Array 1: ', getOddOccuence(inputArray1));
console.log('Input Array 2: ', getOddOccuence(inputArray2));
console.log('Input Array 3: ', getOddOccuence(inputArray3));
In case the input contains multiple or no numbers having odd number of occurance (if you are not sure there) then you have already the hash (and you can ignore performing sum) and return the keys of hash (where value is true (and not checking with %2 and then consider as truthy or false in case of you have count))
function solution(A) {
let result = 0;
for (let element of A) {
// Apply Bitwise XOR to the current and next element
result ^= element;
}
return result;
}
const unpaired = solution([9, 3, 9, 3, 9, 7, 9]);
console.log(unpaired);
Source: https://gist.github.com/k0ff33/3eb60cfb976dee0a0a969fc9f84ae145

How to understand this recursion

Hello all I am trying to understand this solution to combination sum.
function combinationSum(candidates, target) {
var result = [];
if ((candidates == null) || (candidates.length == 0)) {
return result;
}
var cur = [];
candidates = candidates.sort((a, b) => a - b)
csh(candidates, target, cur, result, 0);
return result;
};
function csh(cand, target, cur, result, j) {
//console.log(cur);
if (target == 0) {
var temp = cur.slice();
result.push(temp);
return;
}
for (var i = j; i < cand.length; i++) {
if (target < cand[i]) {
return;
}
//console.log(cur);
cur.push(cand[i]);
console.log(cur);
csh(cand, target - cand[i], cur, result, i);
cur.pop();
}
}
https://leetcode.com/problems/combination-sum/description/
While I understand the basic principles of recursion this problem is a little bit lost on me. So for example for the input:
candidates = [2,3,6,7]
target = 7
When you first enter the function cur is empty so our first iteration is:
[],
[2],
[2,2]
And then we keep adding cand[i] which is currently 2
[2,2,2]
However at this point, target = 1 which is less than cand[i] which is 2 so we return. And since we're returning we pop off the stack which pops the last 2 off the stack. Since we've returned we increment i and then we add 3 to cur
[2,2,3]
Since our target array is equal to 0 we now return again and my question is, at this point do we keep returning until cur is empty and continue the function like the following?
[2,2]
[2]
[]
[6]
[]
[7]
I'm just trying to understand what is being done in this function.
target is local to each invocation of the function. target is 0 only for some invocations of the function. Notice that the recursive invocation is:
csh(cand, target - cand[i], cur, result, i);
The target in that scope has not change, but the invocation of csh currently being entered will have a lower value for its target. When that function returns and the program flow reenters that other level, we resume using the higher value of target, insted of the reduce value target - cand[i] that was supplied to the subcall.
The algorithm will try all other possibilities on the [2,2,...] path as well, before changing the second element to the next alternative. Then it will explore the [2,3,...] space, and the [2,6,...] space, and ultimately all the [3,...], [6,...] and [7,...] possibilities as well.
The algorithm always goes as deep as a possible (i.e., as long of an array as possible) when it can do so without going over the original limit.
Note that it does not produce [2,3,2], because an earlier candidate cannot come after a later one (so a 2 can never be subsequent to a 3 in a result). It enforces this by making the for look start at i = j, where j is the array-depth of the last candidate used, so when the result-in-progress ends with the nth candidate, it only considers nth and higher candidates. this is of practical value because the algorithm only returns one permutation of each value result set: [2,2,3] and [2,3,2] contain the same set of values.
I completely understand that recursion can be very difficult to understand and to explain as well, but here is my take on it.
When csh is called for the 1st time, this is what is being passed
csh(cand, 7, [], [], 0)
Now from the for loop, i = 0, function called is
csh(cand, 5, [2], [], 0)
from the loop, i = 0, function called is
csh(cand, 3, [2,2], [], 0)
from the loop, i = 0, function called is
csh(cand, 1, [2,2,2],[],0)
from the for loop, target(1) < cand[0](2), so return to step Step 4 and pop the last 2 from [2,2,2] resulting in [2,2]
from the loop i = 1, function called is
csh(cand, 0, [2,2,3], [], 1)
here, target == 0 condition is met. so, [2,2,3] is pushed in the result. and then return to step 4. again, 3 is popped from [2,2,3].
from the loop i = 2, target(3) < cand[2](6), so return to step 3. and pop 2 from [2,2] resulting in [2].
from the loop i = 1, function called is
csh(cand, 2, [2,3], [[2,2,3]], 1)
from the loop i = 1, target(2) < cand[1](1) so return to step 9.
and so no...
Basically, each and every combination will be checked.
[2,2,2]
[2,2,3] --> added to result
[2,3,3]
[2,6]
[2,7]
[3,3,3]
[3,6]
[3,7]
[6,6]
[6,7]
[7] --> added to res

Sieve of Eratosthenes in Javascript?

so I was trying to translate this pseudocode from Wikipedia into Javascript:
Input: an integer n > 1
Let A be an array of Boolean values, indexed by integers 2 to n,
initially all set to true.
for i = 2, 3, 4, ..., not exceeding āˆšn:
if A[i] is true:
for j = i^2, i^2+i, i^2+2i, i^2+3i, ..., not exceeding nā€‰:
A[j] := false
Output: all i such that A[i] is true.
And this is as far as I got:
function getPrimes(num) {
var a = [];
for (i=2;i<=num;i++){a.push(true);}
for (i=2;i<=Math.sqrt(num);i++){
for (var j=i*i, coef=0, l=i;j<num-2;coef++){
j = i*i+coef*l-2;
a[j]=false;
}
for (i=0;i<a.length;i++){
if (a[i]){a.splice(i,1,i+2);}
}
}
return a;
}
getPrimes(10); // returns [2, 3, false, 5, false, 7, false, 9, false]
// 9 should be false
So as you can see, the algorithm is not catching all the non-prime numbers. Any idea what I've missed? Thanks in advance to anyone who wants to try their hand at it.
You are overwriting the i variable of the outer loop, with the second inner loop for which you also use i. And so the outer loop only runs once.
Use another variable for the inner loop, like k, and you'll get a good result.
But it is not necessary to have that particular inner loop positioned there. It only has to run once really, just before returning. So you could move it out of the main loop.
A minor issue is that your first inner loop goes too far, as j gets incremented in the body of the loop, and the test on j only happens after you have already assigned a value to a[j]. JavaScript just creates that element at that moment, making the array longer, but it would be nicer if you would prevent that from happening
I would also reserve the first 2 indices of array a for representing numbers 0 and 1, just to make your code more readable: then you don't need those +2 and -2 any more.
Taking all this into account, plus some other optimisations, I would suggest this ES6 code:
function getPrimes(num) {
var a = [...Array(num+1).keys()]; // =[0,1,...,num]
a[1] = 0; // 1 is not prime
var rt = Math.sqrt(num); // calculate only once
for (i=2;i<=rt;i++){
for (var j=i*i; j<=num; j+=i) a[j]=0;
}
return a.filter(Number); // kick out the zeroes
}
// run it for 30
var a = getPrimes(30);
// Output
console.log(a);

Categories

Resources