Sieve of Eratosthenes in Javascript? - 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);

Related

Why does an object exist in two sum solution? [duplicate]

Im just wondering who can explain the algorithm of this solution step by step. I dont know how hashmap works. Can you also give a basic examples using a hashmap for me to understand this algorithm. Thank you!
var twoSum = function(nums, target) {
let hash = {};
for(let i = 0; i < nums.length; i++) {
const n = nums[i];
if(hash[target - n] !== undefined) {
return [hash[target - n], i];
}
hash[n] = i;
}
return [];
}
Your code takes an array of numbers and a target number/sum. It then returns the indexes in the array for two numbers which add up to the target number/sum.
Consider an array of numbers such as [1, 2, 3] and a target of 5. Your task is to find the two numbers in this array which add to 5. One way you can approach this problem is by looping over each number in your array and asking yourself "Is there a number (which I have already seen in my array) which I can add to the current number to get my target sum?".
Well, if we loop over the example array of [1, 2, 3] we first start at index 0 with the number 1. Currently, there are no numbers which we have already seen that we can add with 1 to get our target of 5 as we haven't looped over any numbers yet.
So, so far, we have met the number 1, which was at index 0. This is stored in the hashmap (ie object) as {'1': 0}. Where the key is the number and the value (0) is the index it was seen at. The purpose of the object is to store the numbers we have seen and the indexes they appear at.
Next, the loop continues to index 1, with the current number being 2. We can now ask ourselves the question: Is there a number which I have already seen in my array that I can add to my current number of 2 to get the target sum of 5. The amount needed to add to the current number to get to the target can be obtained by doing target-currentNumber. In this case, we are currently on 2, so we need to add 3 to get to our target sum of 5. Using the hashmap/object, we can check if we have already seen the number 3. To do this, we can try and access the object 3 key by doing obj[target-currentNumber]. Currently, our object only has the key of '1', so when we try and access the 3 key you'll get undefined. This means we haven't seen the number 3 yet, so, as of now, there isn't anything we can add to 2 to get our target sum.
So now our object/hashmap looks like {'1': 0, '2': 1}, as we have seen the number 1 which was at index 0, and we have seen the number 2 which was at index 1.
Finally, we reach the last number in your array which is at index 2. Index 2 of the array holds the number 3. Now again, we ask ourselves the question: Is there a number we have already seen which we can add to 3 (our current number) to get the target sum?. The number we need to add to 3 to get our target number of 5 is 2 (obtained by doing target-currentNumber). We can now check our object to see if we have already seen a number 2 in the array. To do so we can use obj[target-currentNumber] to get the value stored at the key 2, which stores the index of 1. This means that the number 2 does exist in the array, and so we can add it to 3 to reach our target. Since the value was in the object, we can now return our findings. That being the index of where the seen number occurred, and the index of the current number.
In general, the object is used to keep track of all the previously seen numbers in your array and keep a value of the index at which the number was seen at.
Here is an example of running your code. It returns [1, 2], as the numbers at indexes 1 and 2 can be added together to give the target sum of 5:
const twoSum = function(nums, target) {
const hash = {}; // Stores seen numbers: {seenNumber: indexItOccurred}
for (let i = 0; i < nums.length; i++) { // loop through all numbers
const n = nums[i]; // grab the current number `n`.
if (hash[target - n] !== undefined) { // check if the number we need to add to `n` to reach our target has been seen:
return [hash[target - n], i]; // grab the index of the seen number, and the index of the current number
}
hash[n] = i; // update our hash to include the. number we just saw along with its index.
}
return []; // If no numbers add up to equal the `target`, we can return an empty array
}
console.log(twoSum([1, 2, 3], 5)); // [1, 2]
A solution like this might seem over-engineered. You might be wondering why you can't just look at one number in the array, and then look at all the other numbers and see if you come across a number that adds up to equal the target. A solution like that would work perfectly fine, however, it's not very efficient. If you had N numbers in your array, in the worst case (where no two numbers add up to equal your target) you would need to loop through all of these N numbers - that means you would do N iterations. However, for each iteration where you look at a singular number, you would then need to look at each other number using a inner loop. This would mean that for each iteration of your outer loop you would do N iterations of your inner loop. This would result in you doing N*N or N2 work (O(N2) work). Unlike this approach, the solution described in the first half of this answer only needs to do N iterations over the entire array. Using the object, we can find whether or not a number is in the object in constant (O(1)) time, which means that the total work for the above algorithm is only O(N).
For further information about how objects work, you can read about bracket notation and other property accessor methods here.
You may want to check out this method, it worked so well for me and I have written a lot of comments on it to help even a beginner understand better.
let nums = [2, 7, 11, 15];
let target = 9;
function twoSums(arr, t){
let num1;
//create the variable for the first number
let num2;
//create the variable for the second number
let index1;
//create the variable for the index of the first number
let index2;
//create the variable for the index of the second number
for(let i = 0; i < arr.length; i++){
//make a for loop to loop through the array elements
num1 = arr[i];
//assign the array iteration, i, value to the num1 variable
//eg: num1 = arr[0] which is 2
num2 = t - num1;
//get the difference between the target and the number in num1.
//eg: t(9) - num1(2) = 7;
if(arr.includes(num2)){
//check to see if the num2 number, 7, is contained in the array;
index1 = arr.indexOf(num2);
//if yes get the index of the num2 value, 7, from the array,
// eg: the index of 7 in the array is 1;
index2 = arr.indexOf(num1)
//get the index of the num1 value, which is 2, theindex of 2 in the array is 0;
}
}
return(`[${index1}, ${index2}]`);
//return the indexes in block parenthesis. You may choose to create an array and push the values into it, but consider space complexities.
}
console.log(twoSums(nums, target));
//call the function. Remeber we already declared the values at the top already.
//In my opinion, this method is best, it considers both time complexity and space complexityat its lowest value.
//Time complexity: 0(n)
function twoSum(numbers, target) {
for (let i = 0; i < numbers.length; i++) {
for (let j = i + 1; j < numbers.length; j++) {
if (numbers[i] + numbers[j] === target) {
return [numbers.indexOf(numbers[i]), numbers.lastIndexOf(numbers[j])];
}
}
}
}

understanding square brackets in for loop- lesson

I'm currently learning Javascript and would love if someone could help me understand the for loops further. I want to see if someone can give me a bit of an in depth explanation as to how this loop works.
The idea is to return the first non consecutive number in the argument, which as you can see is 6.
Because I'm still learning I wanted to get a detailed yet easy understanding of how this works for example, what's the difference between arr[i]+1 and arr[i+1]?
function firstNonConsec(arr){
for(let i = 0; i < arr.length - 1; i++){
if(arr[i] + 1 !== arr[i+1]){
return arr[i + 1];
}
}
return null
};
console.log(firstNonConsec([1,2,3,4,6,7,8]));
what's the difference between arr[i]+1 and arr[i+1]?
This is not a question about the for loop, but about arrays.
if arr is an array, then you can get the value of one of its items by doing arr[item_number]
arr[i]+1 will therefore give you the value at the place i of the table (e.g. if i equals 0, that would be the first entry in the array), plus one*
arr[i+1] will give you the value at the place i+1 of the table (e.g. if i equals 0, that would be the second entry in the array)
note that +1 can do a lot of things in Javascript, depending on type auto conversion; in your case with only numbers it will increase the number by 1
You can get reference from this workflow of firstNonConsec([1,2,3,4,6,7,8])
i : 0 1 2 3 4 5 6
arr[i] : [ 1, 2, 3, 4, 6, 7, 8 ]
arr[i] + 1 : 2 3 4 5 7 8 9
arr[i+1] : 2 3 4 6 7 8 N
if-statement : T T T F T T F // T: true F: false
return : 2 3 4 N 7 8 N // N: null
arr[i]+1 returns the value of arr's ith array position, then adds one to that value.
arr = [2, 9, 5, 1]
i = 2
arr[2] + 1
Result: 6
So it 1) finds the item in that position 2) adds 1. An array's index starts at 0: arr[n] = [0+n]
You always get the value equal to the result within the bracket.
arr[i+1] would return the i+1th value.
arr = [2, 9, 5, 1]
i = 2
print(arr[i+1]) == print(arr[3])
Result: 1
So this one changes the position itself by 1. This is how a robocaller might complete a call then select the next phone number in a list.
In your case:
if(arr[i] + 1 !== arr[i+1]){
return arr[i + 1];
if the value of the next item in the list is not equal to the previous value + 1, return that value. The function prints you a list of every non consecutive number.
for loop is basically a special type of while loop
var i = 0;
while (i < 10) {
// < code >
i++
}
is the same as
for (let i = 0; i < 10; i++) {
//< code >
}
while loops are used for many different things, so remember them, but for loops are used most. Basically the first "segment" (I'm gonna call whatever's before a semicolon a segment) runs before whatever code you wrote. It usually declares a variable. The second segment runs every time, and stops the loop if the condition isn't met. The third segment also runs every time, but it just runs some code after all the code you wrote is written..
In a lot of languages, including JavaScript, you can also loop through arrays and HashMaps. In JavaScript, you use in and of words.
use for/in for objects
for (let x in < object >) {
//< code >
}
and for each iteration, x is the key of one of the object's properties
to loop through arrays and other iterable objects (you can use for/in, but it's bad practice to), use for/of
for (var x of < array >) {
//< code >
}
this loops through the values of an array, or other such iterable object
the difference between arr[i+1] and arr[i]+1 is that arr[i+1] will access the element after the index specified, but arr[i]+1 will take the value of the index, and return that + 1 (won't change the value, use += to change value). BTW you don't always have to use of for looping thru arrays, you can do it this way which takes i and increases it every time, then takes the value of the index of i.
the answer to your problem:
function firstNonConsec(arr) {
let temp = arr[0];
for (let i = 1; i < arr.length; i++) {
temp = arr[i - 1];
if (temp !== arr[i] - 1) return arr[i];
}
return null;
}
I'm not using for of because you didn't, but comment if you want me to write with for of
Note I used let most of the time because you don't want there to be a random variable that you don't need, and let is limited to the scope of the loop. Also, iterating variables are commonly named i, j, x, y, z and such so you might use i a lot.

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);

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

javascript: how to make function run faster

so i have to write a function which meets the following requirements:
Given a sequence of integers as an array, determine whether it is possible to obtain a strictly increasing sequence by removing no more than one element from the array.
Example:
For sequence = [1, 3, 2, 1], the output should be
almostIncreasingSequence(sequence) = false;
There is no one element in this array that can be removed in order to get a strictly increasing sequence.
For sequence = [1, 3, 2], the output should be
almostIncreasingSequence(sequence) = true.
You can remove 3 from the array to get the strictly increasing sequence [1, 2]. Alternately, you can remove 2 to get the strictly increasing sequence [1, 3].
Input/Output
[time limit] 4000ms (js)
[input] array.integer sequence
Guaranteed constraints:
2 ≤ sequence.length ≤ 105,
-105 ≤ sequence[i] ≤ 105.
so my code works except for one problem--there are 30 tests it has to pass with the time constraint of 4000ms, but it always times out on the 30th test, every time. i have tried modifying it so that it runs faster, but each time i do so it no longer works correctly. although i technically only have to write one function, i broke it up into three separate functions. here's my code:
var greater = function(a, b) {
if (a < b) {
return true
} else {
return false
}
}
function greaterThan(arr) {
for (var i = 0; i < arr.length-1; i++) {
var curr = arr[i]
var next = arr[i + 1]
if (greater(curr, next) === false) {
return false
}
}
return true
}
function almostIncreasingSequence(sequence) {
for(var i = 0; i < sequence.length; i++) {
var newArr = sequence.slice()
newArr.splice(i, 1)
if (greaterThan(newArr) === true) {
return true
}
}
return false
}
so how can i make it run faster without using two for-loops/iterations to do this?
Improving the algorithm may bring better results than improving the code. Here's the problem:
If the sequence is not strictly increasing at index i, such that a[i]>=a[i+1] is true, either a[i] or a[i+1] must be removed to possibly make the array strictly increasing - they can't both be left in place.
If the input array is to be fixable by removing only one element, and it decreases after the ith element it must become strictly increasing by removing the element with subscript i or (i+1).
Compare the efficiency of checking the original array and at most two sub arrays before returning true or false, with checking the same number of arrays as the original array's length. I'll leave re-writing the code to you - it's not my homework :-)

Categories

Resources