Smallest Common Multiple Divisible by - javascript

I'm working in JavaScript and I am solving for smallest common multiple, for two numbers, and the smallest common multiple has to be divisible by all numbers between the two numbers.
Right now, my code is not working at all and nothing is being returned. I had one function to calculate the smallest common multiple and a second function to determine if that multiple was divisible by the numbers between the smallest and largest number.
function smallestCommons(arr) {
var max = 0;
var min = 0;
var lcm = 0;
var max2 = 0;
if(arr[0]> arr[1]) {
max = arr[0];
min = arr[1];
} else {
max = arr[1];
min = arr[0];
}
function range(item){
for(var j = min+1; j < max; j++){
if(item % j !== 0){
return 0;
} else {
return item;
}
}
}
function lcmFind(min1, max1){
for(var i =1; i < min1; i++){
max1 = max1 * i;
if(range(max1) === 0){
continue;
} else {
return range(max1);
}
}
}
return lcmFind(min,max);
}
smallestCommons([1,5]);

You are looking for lcm, or least common multiple. It so happens that lcm(a, b) = a * b / gcd(a, b) where gcd is greatest common divisor, the largest number that both numbers are a multiple of. There is an algorithm called the Euclidean Algorithm for quickly calculating gcd: gcd(a, b) = gcd(b, a % b) where a%b is a modulo b. In javascript, it is this.
function gcd(a, b) {
if (b === 0) {
return a; // so that the recursion does not go on forever
} else {
return gcd(b, a % b);
}
}
Then, you can define lcm like this.
function lcm(a, b) {
return a * b / gcd(a, b);
}
EDIT: In order to calculate the lcm of a list of numbers, just reduce with the lcm function. So in order to calculate the lcm of all numbers in a range, this code will work. (assuming the range is inclusive for the 2 arguments)
function lcmOfRange(a, b) {
let range = [];
for (let i = a; i <= b; i++) {
range.push(i);
}
return lcmOfList(range);
}
function lcmOfList(arr) {
return arr.reduce(lcm);
}
This is equivalent to
function lcmOfRange(a, b) {
let result = a;
for (let i = a + 1; i <= b; i++) {
result = lcm(result, i);
}
return result;
}

Related

How to find if any element within an array is different than 2, 3 and 5 in JavaScript?

The goal is to determine whether a number input is a Hamming number?! Hamming numbers are all numbers that factorized contain just prime numbers 2, 3 and 5. If a number factorized contains any number different than either of 2, 3 and 5 is NOT Hamming number. So I found how to factorize each number input, and factors formed an array. I would like to set up condition whether any factor is different than 2, 3 or 5 to be able to exclude that numbers from potential list of Hamming numbers!
The code that factorize each number to prime factors is:
function getAllFactorsFor(remainder) {
var factors = [], i;
for (i = 2; i <= remainder; i++) {
while ((remainder % i) === 0) {
factors.push(i);
remainder /= i;
}
}
return factors;
}
Now I need to set up condition to exclude all numbers from this newly formed array that contain any prime factors different than 2, 3 and 5!
You can use every order to check that all desired factors are present :
function getAllFactorsFor(remainder) {
var factors = [], i;
for (i = 2; i <= remainder; i++) {
while ((remainder % i) === 0) {
factors.push(i);
remainder /= i;
}
}
return factors;
}
for(let i = 0; i < 20; i++) {
if(getAllFactorsFor(i).every(f => [2, 3, 5].includes(f)))
console.log(`${i} is a Hamming number`);
else
console.log(`${i} is not a Hamming number`);
}
You can use Array.filter with Array.every, for example:
const output = factors.filter(factor => [2,3,5].every(num => num !== factor))
You can use .some(), or more precisely !f.some(x => x > 5) or in text: true if no factors are found that are > 5.
function getAllFactorsFor(remainder) {
var factors = [], i;
for (i = 2; i <= remainder; i++) {
while ((remainder % i) === 0) {
factors.push(i);
remainder /= i;
}
}
return factors;
}
for (var num = 30; num <= 40; num++) {
var f = getAllFactorsFor(num);
console.log(num + " has factors: " + f.toString() + ". Hamming number: " + !f.some(x => x > 5))
}
I've combined different suggestions and googled also and came to my solution version for check up if entered number is Hamming number or not:
The code:
function getAllFactorsFor(remainder) {
var factors = [], i;
for (i = 2; i <= remainder; i++) {
while ((remainder % i) === 0) {
factors.push(i);
remainder /= i;
}
}
return factors;
}
function isHamming(remainder){
if(getAllFactorsFor(remainder).every(f => [2, 3, 5].includes(f))){
return true;
}else{
return false;
}
}

How to convert this O(n^2) algorithm to O(n)?

https://www.codewars.com/kata/is-my-friend-cheating/train/javascript
My goal is to devise a function that finds number pairs (a, b) which satisfy the equation a * b == sum(1, 2, 3 ..., n-2, n-1, n) - a - b.
The following code finds all the pairs, but is too slow and times out. I have seen in the comments for this challenge that the algorithm needs to have O(n) complexity to pass. How is this done?
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let a = n;
while( a !== 0){
let b = n;
while( b !== 0){
if(b != a && a*b == ((sum - b) - a) ){
retArr.push([a,b]);
}
b--;
}
a--;
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
Thanks to all for the assistance! Here is my final solution:
function removeNb (n) {
let retArr = [];
let a = 1;
let b = 0;
let sumN = (n * (n+1))/2;
while( a <= n){
b = parseInt((sumN - a) / (a + 1));
if( b < n && a*b == ((sumN - b) - a) )
retArr.push([a,b]);
a++;
}
return retArr;
}
I think my main issue was an (embarrassing) error with my algebra when I attempted to solve for b. Here are the proper steps for anyone wondering:
a*b = sum(1 to n) - a - b
ab + b = sumN - a
b(a + 1) = sumN - a
b = (sumN - a) / (a + 1)
You can solve for b and get: b = (sum - a)/(a + 1) (given a != -1)
Now iterate over a once -> O(n)
let n = 100;
let sumOfNum = n => {
return (n * (n + 1)) / 2;
};
let sum = sumOfNum(n);
let response = [];
for (let i = 1; i <= 26; i++) {
let s = (sum - i) / (i + 1);
if (s % 1 == 0 && s * i == sum - s - i && s <= n) {
response.push([s, i]);
}
}
// this is O(N) time complexity
Here's an implementation:
function removeNb(n){
var sum = (1 + n) * n / 2;
var candidates = [];
// O(n)
for(var y = n; y >= 1; y--){
x = (-y + sum) / (y + 1);
/*
* Since there are infinite real solutions,
* we only record the integer solutions that
* are 1 <= x <= n.
*/
if(x % 1 == 0 && 1 <= x && x <= n)
// Assuming .push is O(1)
candidates.push([x, y]);
}
// Output is guaranteed to be sorted because
// y is iterated from large to small.
return candidates;
}
console.log(removeNb(26));
console.log(removeNb(100));
https://jsfiddle.net/DerekL/anx2ox49/
From your question, it also states that
Within that sequence, he chooses two numbers, a and b.
However it does not mention that a and b are unique numbers, so a check is not included in the code.
As explained in other answers, it is possible to make a O(n) algorithm solving for b. Moreover, given the symmetry of solution -- if (a,b) is a solution, also (b,a) is -- it is also possible to save some iterations adding a couple of solutions at a time. To know how many iterations are required, let us note that b > a if and only if a < -1+sqrt(1+sum). To prove it:
(sum-a)/(a+1) > a ; sum-a > a^2+a ; sum > a^2+2a ; a^2+2a-sum < 0 ; a_1 < a < a_2
where a_1 and a_2 comes from 2-degree equation solution:
a_1 = -1-sqrt(1+sum) ; a_2 = -1+sqrt(1+sum)
Since a_1 < 0 and a > 0, finally we proved that b > a if and only if a < a_2.
Therefore we can avoid iterations after -1+sqrt(1+sum).
A working example:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) retArr.push([a,b],[b,a]);
}
}
retArr.sort( (a,b) => a[0] - b[0]);
return retArr;
}
However, with this implementation we still need the final sort. To avoid it, we can note that b=(sum-a)/(a+1) is a decreasing function of a (derive it to prove). Therefore we can build retArr concatenating two arrays, one adding elements to the end (push), one adding elements at the beginning (unshift). A working example follows:
function removeNb (n) {
if(n===1) return null;
let sum = (n * (n+1))/2;
let retArr = [];
let retArr2 = [];
for(let a=1;a<Math.round(Math.sqrt(1+sum));++a) {
if((sum-a)%(a+1)===0) {
let b=(sum-a)/(a+1);
if(a!==b && b<=n) {
retArr.push([a,b]);
retArr2.unshift([b,a]); // b>a and b decreases with a
}
}
}
retArr=retArr.concat(retArr2); // the final array is ordered in the 1st component
return retArr;
}
As a non-native speaker, I would say that the phrase from the reference "all (a, b) which are the possible removed numbers in the sequence 1 to n" implies a!=b,
so I added this constraint.

Javascript How to return an array with odd numbers

I'm trying to return an array of numbers
function numbers(l, r) {
// l and r are any given numbers
var x=[];
var i=l;
while(x.push(i++)<r){};
return x;
}
console.log(numbers(10, 19));
So far so good. Now I want to get the odd numbers. How can I achieve that?
x.filter(n => n%2) will keep only odd numbers.
if n is even, n%2 will return 0 and the item will be removed by the filter.
let arr = [1,2,3,4,5,6,7,8,9,10,11,12]
let odds = arr.filter(n => n%2)
console.log(odds)
function* numbers(start, end) {
let i = start%2 ? start : ++start;
while(i <= end) {
yield i;
i += 2
}
}
console.log([...numbers(2, 10)])
or
class Odd {
constructor(l, r) {
this.l = l;
this.r = r;
}
*[Symbol.iterator]() {
let i = this.l % 2 ? this.l : ++(this.l);
while (i <= this.r) {
yield i;
i += 2
}
}
}
const odd = new Odd(2,10);
console.log([...odd])
Provided two values l (starting point) and r (ending point) you would create your array from l to r in increments of +1. Use that array to filter the desired values that meet the mod 2 or % 2 criteria. FYI mod 2 returns 0 if the value is an even number or 1 if the value is an odd number. The filter() method creates a new array with all elements that pass the test implemented by the provided function (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter). Do note that in JavaScript 0 is a falsy value so only positive integer values like 1 are returned thus the array is formed with all values that resulted in n % 2 equal to 1.
function oddNumbers(l, r) {
let arr = [];
while (l <= r) {
arr.push(l);
l += 1;
};
return arr.filter(n => n % 2);
}
You could use an appropriate start value and increment by 2 for each pushing.
function numbers(l, r) {
var x = [],
i = Math.floor(l / 2) * 2 + 1; // start with an odd number
while(i <= r) {
x.push(i);
i += 2;
};
return x;
}
console.log(numbers(10, 19));
console.log(numbers(3, 5));
.as-console-wrapper { max-height: 100% !important; top: 0; }
At first, make i odd:
i = i+1-i%2;
Then iterate over every second:
while(x.push(i+=2)<r){};
Note that this returns r-1 numbers and not numbers up to r-1
Shorter
var EverySecond = (start,length) => Array.from({length}).map((el,i)=>start+i*2);
var even = (start,length) => EverySecond(start+start%2,length);
var odd = (start,length) => EverySecond(start+1-start%2,length);
Try this for pairs:
[0,1,2,3,4].filter(function(n){ return n%2 === 0; });
Try this for odds:
[0,1,2,3,4].filter(function(n){ return n%2 !== 0; });

Is there any way to increase performance for this for loop in JS?

Im trying to solve project euler 10 problem (find the sum of all the primes below two million), but the code takes forever to finish, how do i make it go faster?
console.log("Starting...")
var primes = [1000];
var x = 0;
var n = 0;
var i = 2;
var b = 0;
var sum = 0;
for (i; i < 2000000; i++) {
x = 0;
if (i === 2) {
primes[b] = i
sum += primes[b];
console.log(primes[b]);
b++;
}
for (n = i - 1; n > 1; n--) {
if (i % n === 0) {
x++;
}
if (n === 2 && x === 0) {
primes[b] = i;
sum += primes[b];
console.log(primes[b]);
b++;
}
}
}
console.log(sum)
The biggest super easy things you can do to make this a lot faster:
Break out of the inner loop when you find a divisor!
When you're checking for primality, start with the small divisors instead of the big ones. You'll find the composites a lot faster.
You only have to check for divisors <= Math.sqrt(n)
You only need to check prime divisors. You have a list of them.
Process 2 outside the loop, and then only do odd numbers inside the loop: for(i=3;i<2000000;i+=2)
Here is another version based on the Sieve of Eratosthenes. It requires much more memory but if this does not concern you it's also pretty fast.
// just a helper to create integer arrays
function range(from, to) {
var numbers = [];
for (var i=from ; i<=to ; i++) {
numbers.push(i);
}
return numbers;
}
function primesUpTo(limit) {
if (limit < 2) return [];
var sqrt = Math.floor(Math.sqrt(limit));
var testPrimes = primesUpTo(sqrt);
var numbers = range(sqrt+1, limit);
testPrimes.forEach(function(p) {
numbers = numbers.filter(function(x) { return x % p > 0 });
});
return testPrimes.concat(numbers);
}
var primes = primesUpTo(2000000);
var sum = primes.reduce(function(acc, e) { return acc + e });
Since you keep an array of your primes anyway, you can split the process in two steps:
Generating the primes up to your limit of 2 million
and summing up.
As pointed out by others, you need only check whether a candidate number is divisable by another prime not larger than the square root of the candidate. If you can write a number as a product of primes, then one of those primes will always be lower than or equal to the number's square root.
This code can be optimized further but it is several orders of magnitude faster than your initial version:
function primesUpTo(limit) {
if (limit < 2) return [];
var sqrt = Math.floor(Math.sqrt(limit));
var testPrimes = primesUpTo(sqrt);
var result = [].concat(testPrimes);
for (var i=sqrt+1 ; i<=limit ; i++) {
if (testPrimes.every(function(x) { return (i % x) > 0 })) {
result.push(i);
}
}
return result;
}
var primes = primesUpTo(2000000);
var sum = primes.reduce(function(acc, e) { return acc + e });

Factorialize a Number

I'm taking the freecodecamp course one of the exercises it's to create a Factorialize function, I know there is several ways to do it just not sure what this one keeps returning 5
function factorialize(num) {
var myMax = num;
var myCounter = 1;
var myTotal = 0;
for (i = 0; i>= myMax; i++) {
num = myCounter * (myCounter + 1);
myCounter++;
}
return num;
}
factorialize(5);
This is a recursive solution of your problem:
function factorialize(num) {
if(num <= 1) {
return num
} else {
return num * factorialize(num-1)
}
}
factorialize(5)
This is the iterative solution:
function factorialize(num) {
var cnt = 1;
for (var i = 1; i <= num ; i++) {
cnt *= i;
}
return cnt;
}
factorialize(5)
with argument 5, it will return the 5! or 120.
To answer your question, why your function is returning 5:
Your function never reaches the inner part of the for-loop because your testing if i is greater than myMax instead of less than.
So you are just returning your input parameter which is five.
But the loop does not calculate the factorial of num, it only multiplies (num+1) with (num+2);
My solution in compliance with convention for empty product
function factorializer(int) {
if (int <= 1) {
return 1;
} else {
return int * factorializer(int - 1);
}
}
Here is another way to solve this challenge and I know it is neither the shortest nor the easiest but it is still a valid way.
function factorialiaze(num){
var myArr = []; //declaring an array.
if(num === 0 || num === 1){
return 1;
}
if (num < 0){ //for negative numbers.
return "N/A";
}
for (var i = 1; i <= num; i++){ // creating an array.
myArr.push(i);
}
// Reducing myArr to a single value via .reduce:
num = myArr.reduce(function(a,b){
return a * b;
});
return num;
}
factorialiaze(5);
Maybe you consider another approach.
This solution features a very short - cut to show what is possible to get with an recursive style and a implicit type conversion:
function f(n) { return +!~-n || n * f(n - 1); }
+ convert to number
! not
~ not bitwise
- negative
function f(n) { return +!~-n || n * f(n - 1); }
var i;
for (i = 1; i < 20; i++) {
console.log(f(i));
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this function
const factorialize = (num) => num === 0 ? 1 : num * factorialize(num-1)
Use it like this:
factorialize(5) // returns 120
Try this :
function factorialize(num) {
var value = 1;
if(num === 1 || num ===0) {
return value;
} else {
for(var i = 1; i<num; i++) {
value *= i;
}
return num * value;
}
}
factorialize(5);
// My solution
const factorialize = num => {
let newNum = 1;
for (let i = 1; i <= num; i++) {
newNum *= i
}
return newNum;
}
I love syntactic sugar, so
let factorialize = num => num <= 1 ? num : num * factorialize(num -1)
factorialize(5)

Categories

Resources