Iterating using a quadratic sequence in Javascript - javascript

I have a quadratic sequence in which I need to use to loop over, however, I am not sure how to execute this kind of logic... I want to use the quadratic sequence to count up to a given number <= n. The problem is that I have to give my quadratic sequence for loop some number to count and iterate up to as well... I know it's possible to iterate by 2s, 3s, 4s, etc. by doing things like i += 2, is it possible to use a quadratic expression as well? Is there a method using Javascript in which will allow me to iterate through quadratic sequences? I hope this is clear, thanks!
Here's my code:
The quadratic sequence is the sequence being console logged.
The first 14 terms are: 1,3,6,10,15,21,28,36,45,55,66,78,91,105
for (let i = 1; i <= 14; i++) {
let a = i;
let nthTerm = a - 1;
let b = 1 / 2;
let quadraticSequence = b * a ** 2 + b * a;
console.log(`${nthTerm} ${quadraticSequence}`);
const num = 93;
// use quadratic sequence to count up to a number <= 93;
for (i = 0; i <= num; i++quadraticSequence) {
console.log(i);
}
}
The result should console.log a count 0 > 105. I know the second for loop is not correct, but I'm not quite sure how to approach a proper attempt.
So instead of counting like, 1,2,3,4,5,6,7,8,9... It should count 1,3,6,10,15,21,28,36,45,55... Ultimately, I am trying to count up to a given number <= n (i.e. 93) through the quadratic sequence instead of the usually, 1,2,3,4,5, sequence.

let num = 93;
for (let i = 1, j = 2; i < 100; i += j, j += 1) {
console.log(i);
for (let k = 0; k <= num; k += i) {
console.log(k);
}
}
This will produce the sequence 1, 3, 6, 10, 15, 21, 28, 36, ... and then use each of them in a seperate for loop as step size.
An alternative interpretation would be using the 0th element in the quadratic series as the first step size and the next element as the next step size, etc.
for (let i = 1, j = 2, k = 0; k < 1000; k += i, i += j, j += 1) {
console.log(`Current, step: ${k}, ${i}`);
}
This should do that

Related

Why is the loop not iterating for compounding investment calculation in JS

I'm writing a function to calculate investment return over period of years. However, the function seems to be only able to calculate for one year. If the totalyears is more than 1, the loop as shown below is not iterating and it returns wrong value.
const calc = (initial, monthlyContribution, totalyears, annualisedReturn) => {
let sum = initial;
for (i = 0; i < totalyears; i++) { // ISSUE: THIS NOT LOOPING WHEN totalyears > 1
let balance = sum;
let totalBalance = 0;
for (i = 0; i < 12; i++) {
totalBalance = totalBalance + balance;
balance = balance + monthlyContribution;
}
sum = balance + (totalBalance / 12) * (annualisedReturn / 100);
}
return sum;
};
console.log(calc(0, 100, 2, 10)); // This return 1255 which is wrong
You're using the same global variable for both loops. i will have the value 12 when leaving the inner loop, thus the condition of the outer loop will be false
You are using the same variable "i" in the inner loop and you are not declaring it again.
So when you start the loop with i=0, your inner loop will first make i=0 again, then it will increase until i=12, and then the same variable is used in the first loop, so it will go from 0 to 12, skipping iterations. Use "i, j,k" for nested loops.
Something like this:
for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
}
}

javascript for loop to achieve particular output?

How would I get a standard for loop to output in pairs or other groups (like three's of four's) with the output shifting up one after the last digit of the group?
for(var i = 0: i < 8; i++){
console.log(i)
}
so instead of the output being; 0,1,2,3,4,5,6,7
In pairs it would be; 0,1,1,2,2,3,3,4
or if it went up in groups of four; 0,1,2,3,1,2,3,4
I did try doing something like this, but instead of going up in two's every time I need the loop to output the first 2 digits move up one then output the next two ect...
for(var i = 0: i < 8; i+= 2){
console.log(i)
}
Hope that makes sense
For each case you would need to come up with the right formula based on i:
so instead of the output being; 0,1,2,3,4,5,6,7 In pairs it would be; 0,1,1,2,2,3,3,4
for (let i = 1; i < 9; i++) {
console.log(i >> 1); // this bit shift is integer division by 2
}
or if it went up in groups of four; 0,1,2,3,1,2,3,4
for (let i = 0; i < 8; i++) {
// Perform division by 4 and add remainder to that integer quotient
console.log((i >> 2) + (i % 4));
}
You could work with a variable inside the loop to determine the index. This way you can specify how many times you want the loop to run:
for(let index = 0; index < 8; index++) {
const currentIndex = index - (index >> 1);
console.log(currentIndex);
}
It also makes it easy to implement it as immutable:
const array = new Array(8).fill(0).map((entry, index) => index - (index >> 1));
console.log(array);
I think a function like below where we specify the total n and the chunksize after which you want to increase a single step might work for us :-
function getByChunkSteps(n,chunkSize){
let step = -1;
let output = [];
for(let index = 0;index < n;index++){
if(index%chunkSize===0){
step+=1;
}
output.push((index%chunkSize)+step);
}
return output;
}
console.log(getByChunkSteps(10,2));
console.log(getByChunkSteps(8,4));
console.log(getByChunkSteps(9,3));

What is the Big O for the following functions:

I need help with the following problems on determining what the Big O is of each function.
For problem one, I've tried O(log(n)) and O(n). I figured the function was linear or in other words, for N elements we will require N iterations.
For problem two, I've tried O(n^2). I figured for this kind of order, the worst case time (iterations) is the square of the number of inputs. The time grows exponentially related to the number of inputs.
For problem three, I've tried O(n^2) and O(1).
Problem One:
function foo(array){
let sum = 0;
let product = 1;
for (let i = 0; i < array.length; i++){
sum += array[i]
}
for(let i = 0; i < array.length; i++){
product *= array[i];
}
consle.log(sum + ", " + product);
}
Problem Two:
function printUnorderedParis(array){
for(let i = 0; i < array.length; i++){
for(let j = i + j; j < array.length; j++){
console.log(array[i] + ", " + array[j]);
}
}
}
Problem Three:
function printUnorderedPairs(arrayA, arrayB){
for(let i = 0; i < arrayA.length; i++){
for(let j = 0; i < arrayB.length; j++){
for(let k = 0; k < 100000; k++){
console.log(arrayA[i] + ", " + arrayB[j]);
}
}
}
}
I expected my initial thoughts to be right, but maybe I'm having a hard time grasping Big O.
You're correct that it's O(n). You have two loops, they each perform array.length iterations. You could even combine them into a single loop to make it more obvious.
for (let i = 0; i < array.length; i++) {
sum += array[i];
product *= array[i];
}
You're correct, it's O(n^2). The nested loops perform array.length * array.length iterations.
EDIT -- see my comment above asking whether this problem is copied correctly.
This is also O(n^2). The third level of nested loop doesn't change the complexity, because it performs a fixed number of iterations. Since this doesn't depend on the size of the input, it's treated as a constant. So as far as Big-O is concerned, this is equivalent to Problem 2.
Well, you kind of answered your questions, but here we go:
In the first problem, you have two for loops, each of them iterating over the entire array. For a general array of size n, you'll have O(2n) or simply O(n) since we can let go of constants. There isn't any reasons this would be O(log(n)).
For the second one, I think there is a mistake. The statement j = i + j is not valid, and you'll get Uncaught ReferenceError: j is not defined. However, let's say the statement is actually let j = i. Then, we have:
i, iterating over the entire array, starting from the first element and going all the way to the last one
j, starting from i and going all the way to the last element
With this information, we know that for i = 0, j will iterate from 0 to n (n being the array's length), so n steps. For i=1, j will go from 1 to n, so n-1 steps. Generalizing, we are going to have a sum: n + (n - 1) + (n - 2) + ... + 1 + 0 = n * (n + 1) / 2 = 1/2 * (n^2 + n). So, the complexity is O(1/2 * (n^2 + n) = O(n^2 + n) = O(n). So you were correct.
For the third problem, the answer is O(n^2) and not O(1). The reasoning is very close to the one I made for the second one. Basically, the inner k will be executed 100000 times for every j iteration, but the number of iteration does not depend of n (the size of the array).
It's easy to see that:
for i = 0, j will go from 0 to n (last value for which j body will be executed being j = n - 1).
for j = 0, we will to 100k iterations
for j = 1, another 100k iterations
...
for j = n - 1, another 100k iterations
The entire j loop will make n * 100000 = 100000n iterations.
For i = 1, the same behaviour:
for j = 0, we will to 100k iterations
for j = 1, another 100k iterations
...
for j = n - 1, another 100k iterations,
getting another 100000n iterations.
In the end, we end up with 100000n + 100000n + ... + 100000n (n times) = sum(i = 0, n, 100000n) = n * 100000n = 100000 * n^2. So, the big O is O(100000 * n^2) = O(n^2).
Cheers!

Factorializing a number by creating an array and multiplying it

I am going through one of the FreeCodeCamp challenges.
" Return the factorial of the provided integer.
If the integer is represented with the letter n, a factorial is the
product of all positive integers less than or equal to n.
Factorials are often represented with the shorthand notation n!
For example: 5! = 1 * 2 * 3 * 4 * 5 = 120 "
I already know that the easiest way is to use recursion but by the moment I've discovered this fact I was already trying to solve the problem by creating an array, pushing numbers in it and multiplying them. However I got stuck on this step. I have created an array with the number of digits depending on the function factorialize argument, but I can't get the product of those digits. What did I do wrong:
function factorialize(num) {
var array = [];
var product;
for(i = 0; i<=num;i++) {
array.push(i);
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
}
factorialize(5);
I think the easiest way would be to create a range and reduce that:
var n = 5;
function factorize(max) {
return [...Array(max).keys()].reduce((a,b) => a * (b + 1), 1);
}
console.log(factorize(n));
It looks like you missed a close parenthesis
function factorialize(num) {
var array = [];
var product = 1;
for(i = 0; i<=num;i++) {
array.push(i);
} //right here!!! <----
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
factorialize(5);
but as stated in the comments, you should change i = 0 to i = 1 not just because it would change the final result(which it does for all num ) but because it also doesn't follow the factorial algorithm.
1) You need initial value 'product' variable
2) You should change i = 0 to 1. You multiply by 0 in the loop
3) You don't need nested loop
function factorialize(num) {
var array = [];
var product = 1;
for(var i = 1; i <= num; i++) {
array.push(i);
}
for (j=0; j < array.length; j++) {
product *= array[j];
}
return product;
}
You only need one loop for that,
from 1 to the maximum number, then you multiply them up,
just a little clean up from your code
fact variable will contain the string version of the individual numbers making up the sum
if m is 5 you'll fact will be 1*2*3*4*5
function factorialize(num) {
var product = 1;
var fact = ""
for (i = 1; i <= num; i++) {
product *= i;
fact += i + "*"
}
fact = fact.substring(0, fact.length - 1)
console.log(fact)
return product;
}
console.log(factorialize(5));

Time Complexity: 3Sum algorithm under cubic time?

How can I make use of binary search for improving my algorithms time complexity?
I'm reviewing time complexity for some interviews & I'm having trouble making my algorithm more time efficient. This is my brute force solution for the 3-Sum problem: how many triples sum to exactly 0? Background: I don't have a CS degree.
//BRUTE FORCE SOLUTION: N^3
var threeSum = function(list){
var count = 0;
//checking each triple
for(var i = 0; i < list.length; i++){
for(var j = i+1; j < list.length; j++){
for(var k = j+1; k < list.length; k++){
if(list[i] + list[j] + list[k] === 0){count++;}
}
}
}
return count;
};
//binary search code
var binarySearch = function(target, array){
var lo = 0;
var hi = array.length - 1;
//base case
while(lo <= hi){
var mid = Math.floor( lo + (hi - lo) / 2 );
if(target === array[mid]) return mid;
if(target < array[mid]){
hi = mid - 1;
}
if(target > array[mid]){
lo = mid + 1;
}
}
// value not found
return -1;
}
I was reviewing an algorithms course online from Princeton & the professor noted that this algorithm could be made more efficient with use of a binary search algorithm.
According to the professor we would:
sort the list
for each pair of numbers array[ i ] & array[ j ] binary search for -(array[ i ] + array[ j ])
However, I'm having trouble understanding how binary search comes in to solve the problem. Here is a slide from the lecture, which I'm still trying to understand, but maybe useful to others:
I'm sure there a several efficient solutions out there: feel free to chime in with your implementation as it may help me and other future readers. Thanks
However, I'm having trouble understanding how binary search comes in to solve the problem.
This is how the n^2 log(n) algorithm works:
Sort the list in O(nlogn) time
Find all pairs of numbers (i,j), which is O(n^2) runtime.
Then, for each pair (i,j), it finds a number k where k = sum - j - i. This is constant time O(1)
The algorithm checks to see if each k exists, since the tuple (i,j,k) would sum to sum. To do this, do a binary search which takes log(n) time.
The final runtime would be O(nlogn) + O(logn * n^2) = O(n^2logn)
An alternative (and faster) solution would be to replace the sorting portion with a hashtable. Then, lookup of value k would take O(1) time instead of logn
The problem that the binary search approach is trying to solve is reducing the complexity of a cubic algorithm (this is your brute force algorithm) into a ~ N^2 log N algorithm.
As other commenters pointed out we know that when the following statement: list[i] + list[j] + list[k] == 0 is true than we found a 3SUM result. This is the same as saying that -(list[i] + list[j]) == list[k]. So the goal of the algorithm is to check for each i index and j index pair that there is a corresponding k index which satisfies the previous equation. Binary search can find those k indices in ~log N time. Hence the overall order of growth being ~N^2 log N (the outer for loops correspond to the N^2 part).
As for the implementation in javascript I would do it like this:
var threesum = function(list) {
list.sort(function(a,b){return a - b});
console.log(list);
var cnt = 0;
for(var i=0; i<list.length; i++) {
for(var j=i+1; j<list.length; j++) {
var k = bsearch(-(list[i]+list[j]), list);
if (k!= null && k > j) {
console.log("[i=%d], [j=%d], [k=%d]", i,j,k);
cnt++;
}
}
}
return cnt;
};
var bsearch = function(key, a) {
var lo = 0;
var hi = a.length-1;
while (lo <= hi) {
var mid = lo + Math.floor((hi - lo) / 2);
if (a[mid] < key) {
lo = mid + 1;
} else if (a[mid] > key) {
hi = mid - 1;
} else {
return mid;
}
}
return null;
};
threesum([41, 48, 31, 32, 34, 38, 1, -9, 12, 13, 99, 5, -65, 8, 3, -3])
The algorithm basically works in the following way:
Sort the array (worst-case O(n ^ 2), depending upon sorting algorithm)
Generate all pairs of numbers - takes O(n ^ 2)
for each pair (i , j), there might exist k, such that 0 = i + j + k.kis simply-(i + j), thus we can easily look it up by binary search inO(log n). Cases wherei < k < j` doesn't hold are avoided to exclude duplicates.
Thus total time-complexity is O(n ^ 2 log n).
const threeSum =(array,target)=>{
let result =[]
array = array.sort((a,b)=> a-b)
for(let i=0; i < array.length-2; i++){
let left = i+1;
let right = array.length -1;
while(left < right){
let sum = array[i]+ array[left]+ array[right];
if(sum === target){
result.push([array[i],array[left], array[right]]);
left++;
right--
}else if(sum < target){
//sum is lower than target so increment left pointer
left++;
}else if(sum > target){
//sum is greater than target so increment right pointer
right--;
}
}
}
//return the list
return result;
}
let a = [12, 3, 1, 2, -6, 5, -8, 6];
console.log(threeSum(a, 0));
Time Complexity: O(n^2)
Space Complexity: O(1)

Categories

Resources