how does this loop sequence flows - javascript

I came across a qns which sums the in between of both numbers if they are not equal to each other, I don't quite understand how the statement in the while loop works.
e.g a = 4, b = 0
the end value of sum should be 10 as it is 4+3+2+1+0 = 10
function getSum (a,b)
{
var sum = 0;
while (a !== b)
{
sum += a < b ? a++:b++;
}
return sum+a
}
Am i suppose to see it as
(sum+=a) < b ? a++:b++
OR
sum += (a < b) ? a++:b++
where the conditions are the ones in bold
(edit : I know the conditions is before the ? for the second part just trying to make it clearer if i were to follow through the loop, am i suppose to do the ones in bold first as I got lost despite writing it down in pen and paper)
If anyone can teach / help break down the loop sequence step by step, thanks a lot!

As += is an assignment operation, it is one of the last operations to be executed. Therefore,
sum += (a < b) ? a++:b++ is the correct equivalent.
This line is equivalent to:
if (a<b) {
sum += a++;
}
else {
sum += b++;
}

Related

Counting every 5th for loop

I'm having a hard time with this problem here:
Write a function named sumEvery5th that accepts a non-negative integer n and returns the sum of the integers divisible by 5 from 1 to n, including n itself. Use a for loop.
This is what I have so far:
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; n % 5 == 0; i++){
sum+ i
};
return sum;
}
I feel like I'm really close. Thanks for the help in advance.
You can start your loop at 5, since 1, 2... are not divisible by 5. And instead of i++, you can directly go 5 by 5, until i is greater than n:
var sumEvery5th = function(n) {
let sum = 0;
for (let i = 5; i <= n; i += 5) {
sum += i;
};
return sum;
}
console.log(sumEvery5th(10)); // 5 + 10 = 15
console.log(sumEvery5th(18)); // 5 + 10 + 15 = 30
First I think you should understand how a for loop works.
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; n % 5 == 0; i++){
sum+ i
};
return sum;
}
What you are doing, step by step, is:
Declaring a variable i with value 1.
Dividing n by 5 and taking the remainder value and comparing it with 0. In case it's true, you are skipping the code block inside the for and moving towards the return sum; line.
(In case you haven't skipped the code block in step 2) Run the code block with the new i value.
(In case you haven't skipped the code block in step 2) Incrementing the i value.
Go back to step 2.
Usually your for condition will depend in the variable declared in step 1. What you want to do is run the for code block n times.
For that, you need to change your condition from n % 5 == 0 to i <= n. This will make sure to run the code block while your i is less or equal than n, starting with a value of 1.
Now, inside your code block you add your divisible by 5 logic, checking against i value.
for(let i = 1; i <= n; i++){
if (i%5 == 0) sum += i;
};
Now let's say I called sumEvery5th(5).
Declare a variable i with value 1.
Check if i (1) is less than or equal n (5).
Go inside the code block.
Check if i%5 is 0.
It's not.
Increment i, now i = 2.
Check if i (2) is less than or equal n (5).
...And so on, until i = 6, and in that case the code block is skipped and the program will continue its course.
Ps.: There are ways to improve the performance of this algorithm, but now that you understand your for loop a bit better I'll leave it to you :)
var sumEvery5th = function(n){
let sum = 0;
for(let i = 1; i <= n; i++){
if (i % 5 === 0) {
sum += i;
}
}
return sum;
}

Javascript Time Complexity Analysis

Hi there I have been researching and trying to learn how to check for the time complexity of certain algorithms. I've seen this video which was very helpful.
That being said I wondered off and started trying to work out the Worsts Case and an average case of certain algorithms.
1
I believe in the following snippet it is O(n) since to ind the value for sin we have to loop the entire array.
function mySin(x, iterNum) {
var mxx = -x*x;
var sin = 1;
var n = 0;
var term = 1;
for (var i = 1; i <= 2*iterNum; i++) {
n = n + 2;
term = term * mxx / ( n*(n+1) );
sin = sin + term
}
sin = x*sin;
console.log(sin + " = my function.");
console.log(Math.sin(x) + " math.sin");
}
Thanks again
2
function calculateFibonacciSum (num) {
if(cachedNumbers[num]) {
return cachedNumbers[num];
}
if(('number' === typeof num) && num <= 0) {
throw new Error ('Fibonnci series starts with 0. Please, enter any interget greater than or equal to 0');
}
else if(('number' === typeof num) && num === 0) {
return 0;
}
else if(('number' === typeof num) && (num === 1 || num === 2)) {
return 1;
}
else {
var value = calculateFibonacciSum(num-1) + calculateFibonacciSum(num-2);
cachedNumbers[num] = value;
return value;
}
}
While for this one I think it is also O(n) since in the first if/else statement the tc is O(1) since its contestant whilst the final else statement we must loop all the numbers and if the number is not calculated then call the function again (aka recurssion).
TIA
Both of these seem correct to me. Here's a bit more explanation:
1.
This is in fact O(n), as there are n iterations of the loop, the rest constant time; and n is proportional to iterNum
2.
This one is also linear time, but only since you cache the results of previous calculations. Otherwise it would be O(2n).
It is linear time since it essentially runs a loop down to the base cases (0 and 1). In fact, you could re-write this one using a loop instead of recursion.

Find a subset of a list of given size that sums to target value

I entered a coding test where one of the questions was this: given an array A of integers of any length, and then two numbers N and Z, say whether there are Z (distinct) numbers in A such as their sum is N.
So for example (in the format A N Z):
for [1,2,3] 5 2 the answer is YES because 2+3=5
for [1,2,3] 6 2 the answer is NO because there are no two numbers in A that can be added to make 6
My solution (below) first enumerates every (unordered) combination of Z numbers in A, then sums it, and then searches for N in the list of sums.
Although this solution works fine (passed all test cases, with no timeout), I was told the score was too low for me to continue in the test.
So the question is, what can be improved?
An obvious optimization would be to calculate the sum of each combination immediately, and then stop when a match with N is found; but since I didn't run into time issues I don't think this is the problem. What is the better, more elegant/efficient solution?
function main(a, n, z) {
var spacea = [], // array of unordered combinations of z integers from a
space = [], // array of unique sums of combinations from spacea
res=0; // result (1 or 0)
// produce combination
spacea = combo(a,z);
// put unique sums in space
spacea.forEach(function(arr) {
var s = arr.reduce(function(a,b) {
return a+b;
});
if (space.indexOf(s)<0) space.push(s);
});
// is n in space?
res = space.indexOf(n) === -1 ? "NO" :"YES";
return res;
}
// produces combinations (outputs array of arrays)
function combo(a, z) {
var i,
r = [],
head,
right;
if (z > a.length || z <= 0) {
// do nothing, r is already set to []
}
else if (a.length === z) {
r = [a];
}
else if (1 === z) {
// r = array of array of values from a
a.forEach(function(e) {
r.push([e]);
});
}
else { // by virtue of above tests, z>1 and z<a.length
for (i=0; i<a.length-z+1; i++) {
head = a.slice(i, i+1);
right = combo(a.slice(i+1), z-1);
right.forEach(function(e) {
r.push(head.concat(e));
});
}
}
return r;
}
This is a variation of the subset sum problem, which can be solved with Dynamic Programming for more efficient solution.
The main difference here, is you have an extra restriction - the number of elements that must be used. This extra restriction can be handled by adding another variable (dimension) - the number of already used elements.
The recursive formulas (which you will build the DP solution from) should be:
D(0,0,0) = true
D(i,k,x) = false if i < 0 or k < 0
D(i,k,x) = D(i-1, k, x) OR D(i-1, k-1, x - arr[i])
In the above, D(i,k,x) is true if and only if there is a solution that uses k exactly k numbers, from the first i elements, and sums to x.
Complexity of this solution is O(n*N*Z) where n - number of elements in the array, N - number of distinct elements you can use, Z - target sum.

Euler Project 2 in Javascript

I am going through the Odin Project and part of that is doing questions 1-3 in the Euler project. I am stumped on question 2:
"By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms."
I am so frustrated! What am I doing wrong? Here's what I have so far. Thanks!
function f() {
var fib = [];
fib.push(1,2,3);
var i = fib.length;
var total = 0;
while(fib[i] < 4000000) {
var x = fib[i-2] + fib [i-1];
if(x % 2 == 0) {
total += x;
}
} return total;
}
console.log(f());
The fibonacci sequences starts 1, 1, 2, not 1, 2, 3.
Also, your solution looks like it will work, but you are storing every number in the sequence instead of just the last two, so this will gobble memory comparatively.
As #DLeh notes, the fibonacci sequence starts with 1,1,2 - not 1,2,3. However, that doesn't change the result of summing the even valued items. The problem you're having is that at this point:
while(fib[i] < 4000000) {
fib[i] is undefined, so the function immediately exits with the total staying at 0. Also within the while loop, you're not pushing the next item in the sequence into your array. The below code fixes both of these problems:
function f() {
var fib = [];
fib.push(1,1);
var i = fib.length;
var total = 0;
while(fib[i-1] < 4000000) {
var x = fib[i-2] + fib [i-1];
fib.push(x);
i = fib.length;
if(x % 2 == 0) {
total += x;
}
} return total;
}
console.log(f()); //4613732
#DLeh also pointed out that you're storing more numbers than needed, this solution works without using the array:
function f() {
var f1 = 1;
var f2 = 1;
var total = 0;
while (f2 < 4000000) {
var t = f1 + f2;
if (t % 2 == 0)
total += t;
f1 = f2;
f2 = t;
}
return total;
}
console.log(f()); //4613732
Just for grins, note that you can do this problem without any use of %, and just + operations. Every third value in the sequence is even. That is, 2 is followed by 3 (odd), and then 3 + 2 is 5 (odd), but that sum of two odd numbers gets us back to even (8) and the cycle repeats.
Thus:
function evenFibTotal(limit) {
var a = 1, b = 1, c = 2, total = 0;
while (c < limit) {
total += c;
a = b + c;
b = a + c;
c = a + b;
}
return total;
}
On each iteration, the second trailing value is set to the next value in the sequence (b + c), and that plus the current one is the first trailing value, and finally the next even Fibonacci number is the sum of those two.
(There's also the closed solution but it's no fun :)

Using Recursion for Additive Persistence

I'm trying to solve a Coderbyte challenge, and I'm still trying to fully understand recursion.
Here's the problem: Using the JavaScript language, have the function AdditivePersistence(num) take the num parameter being passed which will always be a positive integer and return its additive persistence which is the number of times you must add the digits in num until you reach a single digit. For example: if num is 2718 then your program should return 2 because 2 + 7 + 1 + 8 = 18 and 1 + 8 = 9 and you stop at 9.
Here's the solution I put into jsfiddle.net to try out:
function AdditivePersistence(num) {
var count=0;
var sum=0;
var x = num.toString().split('');
for(var i=0; i<x.length; i++) {
sum += parseInt(x[i]);
}
if(sum.length == 1) {
return sum;
}
else {
return AdditivePersistence(sum);
}
}
alert(AdditivePersistence(19));
It tells me that there's too much recursion. Is there another "else" I could put that would basically just re-run the function until the sum was one digit?
One of the problems is that your if statement will never evaluate as 'true'. The reason being is that the sum variable is holding a number, and numbers don't have a length function. Also, as 'Barmar' pointed out, you haven't incremented the count variable, and neither are you returning the count variable.
Here's a solution that works using recursion.
function AdditivePersistence(num) {
var result = recursive(String(num).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), 1);
function recursive(n, count){
c = count;
if(n < 10)return c;
else{
count += 1
return recursive(String(n).split('').reduce(function(x,y){return parseInt(x) + parseInt(y)}), count)
}
}
return num < 10 ? 0 : result
}
To fix the 'too much recursion problem',
if(sum.toString().length == 1)
However, as the others have said, your implementation does not return the Additive Persistence. Use James Farrell's answer to solve the Coderbyte challenge.

Categories