A codility problem asks to find the missing number in zero-indexed array A consisting of N different integers.
E.g.
Arr[0] = 2
Arr[1] = 3
Arr[2] = 1
Arr[3] = 4
Arr[4] = 6
I previously submitted a solution that first sorts the array and then performs a forEach function returning the value +1 where the array difference between elements is more than 1, however this doesn't get the 100 points.
Is there a way to improve this?
Here is 100% javascript solution:
function solution(A) {
if (!A.length) return 1;
let n = A.length + 1;
return (n + (n * n - n) / 2) - A.reduce((a, b) => a + b);
}
We return 1 if the given array is empty, which is the missing element in an empty array.
Next we calculate the 'ordinary' series sum, assuming the first element in the series is always 1. Then we find the difference between the given array and the full series, and return it. This is the missing element.
The mathematical function I used here are series sum, and last element:
Sn = (n/2)*(a1 + an)
an = a1 + (n - 1)*d
Get 100 in correctness and performance using this function
function solution(A) {
// write your code in JavaScript (Node.js 4.0.0)
var size = A.length;
var sum = (size + 1) * (size + 2) / 2;
for (i = 0; i < size; i++) {
sum -= A[i];
}
return sum;
}
Easy if you use the Gauss formula to calculate the sum of the first N consecutive numbers:
function solution(A) {
var np1, perfectSum, sum;
if (!A || A.length == 0) {
return 1;
}
np1 = A.length + 1;
// Gauss formula
perfectSum = np1 * (1 + np1) / 2;
// Sum the numbers we have
sum = A.reduce((prev, current) => prev + current);
return perfectSum - sum;
}
From the sum of first natural numbers formula we have
now since the N item for us in the task is (N+1) we substitue n with n+1 and we get
with the formula above we can calculate the sum of numbers from 1 to n+1, since in between these numbers there is the missing number, now what we can do is we can start iterating through the given array A and subtracting the array item from the sum of numbers. The ending sum is the item which was missing in the array. hence:
function solution(A) {
var n = A.length;
// using formula of first natural numbers
var sum = (n + 1) * (n + 2) / 2;
for (var i = 0; i < n; i++) {
sum -= A[i];
}
return sum;
}
No Gauss formula, only simple and plain separate for loops that give an O(N) or O(N * log(N)) and 100% score:
function solution(A) {
if(!A.length){
return 1; //Just because if empty this is the only one missing.
}
let fullSum = 0;
let sum = 0;
for(let i = 0; i <= A.length; i++){
fullSum += i+1;
}
for(let i = 0; i < A.length; i++){
sum += A[i];
}
return fullSum - sum;
}
Try utilizing Math.min , Math.max , while loop
var Arr = [];
Arr[0] = 2
Arr[1] = 3
Arr[2] = 1
Arr[3] = 4
Arr[4] = 6
var min = Math.min.apply(Math, Arr),
max = Math.max.apply(Math, Arr),
n = max - 1;
while (n > min) {
if (Arr.indexOf(n) === -1) {
console.log(n);
break;
}
--n;
}
This should be work good:
function solution(A) {
// Size of the A array
const size = A.length;
// sum of the current values
const arrSum = A.reduce((a, b) => a + b, 0);
// sum of all values including the missing number
const sum = (size + 1) * (size + 2) / 2;
// return substruction of all - current
return (sum - arrSum);
}
This got me 100%
function solution(A) {
if (A.length === 0 || !A) {
return 1;
}
A.sort((a, b) => a - b);
let count = A[0];
if (count !== 1) { return 1 }
for (let i = 0; i <= A.length; i++) {
if (A[i + 1] === count + 1) {
count ++;
continue
}
return count + 1;
}
}
// you can write to stdout for debugging purposes, e.g.
// console.log('this is a debug message');
function solution(A) {
if (!A.length) return 1;
A = A.sort((a, b) => a - b);
for (let i = 0; i < A.length + 1; i++) {
if (A[i] !== i + 1) {
return i + 1;
}
}
}
My 100% JavaScript solution:
function solution(A) {
const N = A.length;
// use the Gauss formula
const sumNatural = (N + 1) * (N + 2) / 2;
// actual sum with the missing number (smaller than sumNatural above)
const actualSum = A.reduce((sum, num) => sum += num, 0);
// the difference between sums is the missing number
return sumNatural - actualSum;
}
I wonder why there isn't any answer using a hashtable.
It's obvious that we need to iterate this array from start to end.
Therefore, best solution we can have is O(n).
I simply map numbers, and access them with O(1) in another iteration.
If all numbers are tagged as true, it means it's either an empty array, or it doesn't contain missing number. Either way length + 1 returns the expected output.
It returns 1 for [], and it returns 3 for [1,2].
// you can write to stdout for debugging purposes, e.g.
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
let nums = new Map()
for (let i = 0; i < A.length; i++) {
nums[A[i]] = true;
}
for (let i = 1; i < A.length + 1; i++) {
if (nums[i]) { continue; }
else { return i;}
}
return A.length + 1;
}
function solution(A) {
// write your code in JavaScript (Node.js 8.9.4)
const n = A.length+1
return (n*(n+1)/2) - A.reduce((a, b) => a + b, 0)
}
Explanation:
The formula for sum of natural numbers => n(n+1)/2
where n is the last number or last nth term.
In our case, n will be our array.length. But the question states that exactly one item is missing, meaning the last nth term is array.length +1.
To find the expected sum of all our natural numbers,
We can deduct the total of the available numbers (A.reduce((a, b) => a + b, 0)) from the expected sum n(n+1)/2 to arrive at the missing number.
I had the same problem with my code:
function solution(A) {
var i, next;
A.sort();
next = 1;
for (i=0; i<A.length; i++){
if (A[i] != next) return next;
next++;
}
return next;
}
Altough it scored 100% in correctness, it returned wrong answer in all the performance tests.
The same code in C receives 100% on both:
int cmpfunc (const void * a, const void * b){
return ( *(int*)a - *(int*)b );
}
int solution(int a[], int n) {
int i, next;
qsort(a, n, sizeof(int), cmpfunc);
next = 1;
for (i=0; i<n; i++){
if (a[i] != next) return next;
next++;
}
return next;
}
I got an alternative 100% correctness/performance solution without the Gauss formula, sorting the array first instead:
function solution(A) {
A.sort((a, b) => a-b);
for(let i=0; i<A.length; i++){
if(A[i] != i+1) {
return 0;
}
}
return 1;
}
Given an array of two numbers, let them define the start and end of a range of numbers. For example, [2,6] means the range 2,3,4,5,6. I want to write javascript code to find the least common multiple for the range. My code below works for small ranges only, not something like [1,13] (which is the range 1,2,3,4,5,6,7,8,9,10,11,12,13), which causes a stack overflow. How can I efficiently find the least common multiple of a range?
function leastCommonMultiple(arr) {
var minn, max;
if ( arr[0] > arr[1] ) {
minn = arr[1];
max = arr[0];
} else {
minn = arr[0];
max = arr[1];
}
function repeatRecurse(min, max, scm) {
if ( scm % min === 0 && min < max ) {
return repeatRecurse(min+1, max, scm);
} else if ( scm % min !== 0 && min < max ) {
return repeatRecurse(minn, max, scm+max);
}
return scm;
}
return repeatRecurse(minn, max, max);
}
I think this gets the job done.
function leastCommonMultiple(min, max) {
function range(min, max) {
var arr = [];
for (var i = min; i <= max; i++) {
arr.push(i);
}
return arr;
}
function gcd(a, b) {
return !b ? a : gcd(b, a % b);
}
function lcm(a, b) {
return (a * b) / gcd(a, b);
}
var multiple = min;
range(min, max).forEach(function(n) {
multiple = lcm(multiple, n);
});
return multiple;
}
leastCommonMultiple(1, 13); // => 360360
function smallestCommons(arr) {
var max = Math.max(...arr);
var min = Math.min(...arr);
var candidate = max;
var smallestCommon = function(low, high) {
// inner function to use 'high' variable
function scm(l, h) {
if (h % l === 0) {
return h;
} else {
return scm(l, h + high);
}
}
return scm(low, high);
};
for (var i = min; i <= max; i += 1) {
candidate = smallestCommon(i, candidate);
}
return candidate;
}
smallestCommons([5, 1]); // should return 60
smallestCommons([1, 13]); // should return 360360
smallestCommons([23, 18]); //should return 6056820
LCM function for a range [a, b]
// Euclid algorithm for Greates Common Divisor
function gcd(a, b)
{
return !b ? a : gcd(b, a % b);
}
// Least Common Multiple function
function lcm(a, b)
{
return a * (b / gcd(a,b));
}
// LCM of all numbers in the range of arr=[a, b]
function range_lcm(arr)
{
// Swap [big, small] to [small, big]
if(arr[0] > arr[1]) (arr = [arr[1], arr[0]]);
for(x = result = arr[0]; x <= arr[1]; x++) {
result = lcm(x, result);
}
return result;
}
alert(range_lcm([8, 5])); // Returns 840
As this question has recently been revived, here's what I think is a simpler take on the question, writing very simple helper functions to calculate the greatest common divisor of two integers (gcd), to calculate the least common multiple of two integers (lcm), to calculate the least common multiple of an array of integers (lcmAll), to generate the range of integers between two given integers (rng), and finally, in our main function, to calculate the least common multiple of the range of integers between two given integers (lcmRng):
const gcd = (a, b) => b == 0 ? a : gcd (b, a % b)
const lcm = (a, b) => a / gcd (a, b) * b
const lcmAll = (ns) => ns .reduce (lcm, 1)
const rng = (lo, hi) => [...Array (hi - lo + 1)] .map ((_, i) => lo + i)
const lcmRng = (lo, hi) => lcmAll (rng (lo, hi))
console .log (lcmRng (1, 13))
All of these functions are simple. Although the question was tagged recursion, only gcdis recursive. If this is an attempt to play with recursion, we could rewrite lcmAll in a recursive manner with something like this:
const lcmAll = (ns) =>
ns.length == 0
? 1
: lcm(ns[0], lcmAll(ns .slice (1)))
Although I'm a big fan of recursion, I see no other reason to choose the recursive version here over the reduce one. In this case, reduce is cleaner.
And finally, if you really want the API originally requested where the range bounds are passed in an array, you could write one more wrapper:
const leastCommonMultiple = ([lo, hi]) => lcmRng (lo, hi)
leastCommonMultiple ([1, 13]) //=> 360360
I found the other answers to be somewhat confusing while I was figuring out the best way to do this with just two numbers, so I looked found the most optimal solution on Wikipedia.
https://en.wikipedia.org/wiki/Least_common_multiple#Calculation
The most efficient way to find the least common multiple of two numbers is (a * b) / greatestCommonDivisor(a, b);
To do this we need to calculate the greatest common denominator. The most efficient way to do that is using Euclid's algorithm.
https://en.wikipedia.org/wiki/Greatest_common_divisor#Euclid's_algorithm
Here is the complete solution for two numbers in case anyone else lands on this question but only needs to calculate for two numbers:
const leastCommonMultiple = (a, b) => (a * b) / greatestCommonDivisor(a, b);
const greatestCommonDivisor = (a, b) => {
const remainder = a % b;
if (remainder === 0) return b;
return greatestCommonDivisor(b, remainder);
};
Mine is not as fancy as the other answers but I think it is easy to read.
function smallestCommons(arr) {
//order our array so we know which number is smallest and which is largest
var sortedArr = arr.sort(sortNumber),
//the smallest common multiple that leaves no remainder when divided by all the numbers in the rang
smallestCommon = 0,
//smallest multiple will always be the largest number * 1;
multiple = sortedArr[1];
while(smallestCommon === 0) {
//check all numbers in our range
for(var i = sortedArr[0]; i <= sortedArr[1]; i++ ){
if(multiple % i !== 0 ){
//if we find even one value between our set that is not perfectly divisible, we can skip to the next multiple
break;
}
//if we make it all the way to the last value (sortedArr[1]) then we know that this multiple was perfectly divisible into all values in the range
if(i == sortedArr[1]){
smallestCommon = multiple;
}
}
//move to the next multiple, we can just add the highest number.
multiple += sortedArr[1];
}
console.log(smallestCommon);
return smallestCommon;
}
function sortNumber(a, b) {
return a - b;
}
smallestCommons([1, 5]); // should return 60.
smallestCommons([5, 1]); // should return 60.
smallestCommons([1, 13]); // should return 360360.
smallestCommons([23, 18]); // should return 6056820.
Edit: Turned answer into snippet.
This is a non-recursive version of your original approach.
function smallestCommons(arr) {
// Sort the array
arr = arr.sort(function (a, b) {return a - b}); // numeric comparison;
var min = arr[0];
var max = arr[1];
var numbers = [];
var count = 0;
//Here push the range of values into an array
for (var i = min; i <= max; i++) {
numbers.push(i);
}
//Here freeze a multiple candidate starting from the biggest array value - call it j
for (var j = max; j <= 1000000; j+=max) {
//I increase the denominator from min to max
for (var k = arr[0]; k <= arr[1]; k++) {
if (j % k === 0) { // every time the modulus is 0 increase a counting
count++; // variable
}
}
//If the counting variable equals the lenght of the range, this candidate is the least common value
if (count === numbers.length) {
return j;
}
else{
count = 0; // set count to 0 in order to test another candidate
}
}
}
alert(smallestCommons([1, 5]));
Hey I came across this page and wanted to share my solution :)
function smallestCommons(arr) {
var max = Math.max(arr[0], arr[1]),
min = Math.min(arr[0], arr[1]),
i = 1;
while (true) {
var count = 0;
for (j = min; j < max; j++) {
if (max * i % j !== 0) {
break;
}
count++;
}
if (count === (max - min)) {
alert(max * i);
return max * i;
}
i++;
}
}
smallestCommons([23, 18]);
function leastCommonMultiple(arr) {
/*
function range(min, max) {
var arr = [];
for (var i = min; i <= max; i++) {
arr.push(i);
}
return arr;
}
*/
var min, range;
range = arr;
if(arr[0] > arr[1]){
min = arr[1];
}
else{
min = arr[0]
}
function gcd(a, b) {
return !b ? a : gcd(b, a % b);
}
function lcm(a, b) {
return (a * b) / gcd(a, b);
}
var multiple = min;
range.forEach(function(n) {
multiple = lcm(multiple, n);
});
return multiple;
}
console.log( leastCommonMultiple([1, 13]) )
Well played on the solution. I think I got one that might be abit shorter just for future reference but ill definatly look into yours
function LCM(arrayRange) {
var newArr = [];
for (var j = arrayRange[0]; j <= arrayRange[1]; j++){
newArr.push(j);
}
var a = Math.abs(newArr[0]);
for (var i = 1; i < newArr.length; i++) {
var b = Math.abs(newArr[i]),
c = a;
while (a && b) {
a > b ? a %= b : b %= a;
}
a = Math.abs(c * newArr[i] / (a + b))
}
return console.log(a);
}
LCM([1,5]);
You may have originally had a stack overflow because of a typo: you switched between min and minn in the middle of repeatRecurse (you would have caught that if repeatRecurse hadn’t been defined in the outer function). With that fixed, repeatRecurse(1,13,13) returns 156.
The obvious answer to avoiding a stack overflow is to turn a recursive function into a non-recursive function. You can accomplish that by doing:
function repeatRecurse(min, max, scm) {
while ( min < max ) {
while ( scm % min !== 0 ) {
scm += max;
}
min++;
}
}
But perhaps you can see the mistake at this point: you’re not ensuring that scm is still divisible by the elements that came before min. For example, repeatRecurse(3,5,5)=repeatRecurse(4,5,15)=20. Instead of adding max, you want to replace scm with its least common multiple with min. You can use rgbchris’s gcd (for integers, !b is the same thing as b===0). If you want to keep the tail optimization (although I don’t think any javascript engine has tail optimization), you’d end up with:
function repeatRecurse(min, max, scm) {
if ( min < max ) {
return repeatRecurse(min+1, max, lcm(scm,min));
}
return scm;
}
Or without the recursion:
function repeatRecurse(min,max,scm) {
while ( min < max ) {
scm = lcm(scm,min);
min++;
}
return scm;
}
This is essentially equivalent to rgbchris’s solution. A more elegant method may be divide and conquer:
function repeatRecurse(min,max) {
if ( min === max ) {
return min;
}
var middle = Math.floor((min+max)/2);
return lcm(repeatRecurse(min,middle),repeatRecurse(middle+1,max));
}
I would recommend moving away from the original argument being an array of two numbers. For one thing, it ends up causing you to talk about two different arrays: [min,max] and the range array. For another thing, it would be very easy to pass a longer array and never realize you’ve done something wrong. It’s also requiring several lines of code to determine the min and max, when those should have been determined by the caller.
Finally, if you’ll be working with truly large numbers, it may be better to find the least common multiple using the prime factorization of the numbers.
function range(min, max) {
var arr = [];
for (var i = min; i <= max; i++) {
arr.push(i);
}
return arr;
}
function gcd (x, y) {
return (x % y === 0) ? y : gcd(y, x%y);
}
function lcm (x, y) {
return (x * y) / gcd(x, y);
}
function lcmForArr (min, max) {
var arr = range(min, max);
return arr.reduce(function(x, y) {
return lcm(x, y);
});
}
range(10, 15); // [10, 11, 12, 13, 14, 15]
gcd(10, 15); // 5
lcm(10, 15); // 30
lcmForArr(10, 15); //60060
How about:
// Euclid Algorithm for the Greatest Common Denominator
function gcd(a, b) {
return !b ? a : gcd(b, a % b);
}
// Euclid Algorithm for the Least Common Multiple
function lcm(a, b) {
return a * (b / gcd(a, b));
}
// LCM of all numbers in the range of arr = [a, b];
function smallestCommons(arr) {
var i, result;
// large to small - small to large
if (arr[0] > arr[1]) {
arr.reverse();
} // only happens once. Means that the order of the arr reversed.
for (i = result = arr[0]; i <= arr[1]; i++) { // all numbers up to arr[1] are arr[0].
result = lcm(i, result); // lcm() makes arr int an integer because of the arithmetic operator.
}
return result;
}
smallestCommons([5, 1]); // returns 60
function lcm(arr) {
var max = Math.max(arr[0],arr[1]),
min = Math.min(arr[0],arr[1]),
lcm = max;
var calcLcm = function(a,b){
var mult=1;
for(var j=1; j<=a; j++){
mult=b*j;
if(mult%a === 0){
return mult;
}
}
};
for(var i=max-1;i>=min;i--){
lcm=calcLcm(i,lcm);
}
return lcm;
}
lcm([1,13]); //should return 360360.
/*Function to calculate sequential numbers
in the range between the arg values, both inclusive.*/
function smallestCommons(arg1, arg2) {
if(arg1>arg2) { // Swap arg1 and arg2 if arg1 is greater than arg2
var temp = arg1;
arg1 = arg2;
arg2 =temp;
}
/*
Helper function to calculate greatest common divisor (gcd)
implementing Euclidean algorithm */
function gcd(a, b) {
return b===0 ? a : gcd(b, a % b);
}
/*
Helper function to calculate lowest common multiple (lcm)
of any two numbers using gcd function above */
function lcm(a,b){
return (a*b)/gcd(a,b);
}
var total = arg1; // copy min value
for(var i=arg1;i<arg2;i++){
total = lcm(total,i+1);
}
//return that total
return total;
}
/*Yes, there are many solutions that can get the job done.
Check this out, same approach but different view point.
*/
console.log(smallestCommons(13,1)); //360360
Here's my solution. I hope you will find it easy to follow:
function smallestCommons(arr) {
var min = Math.min(arr[0], arr[1]);
var max = Math.max(arr[0], arr[1]);
var smallestCommon = min * max;
var doneCalc = 0;
while (doneCalc === 0) {
for (var i = min; i <= max; i++) {
if (smallestCommon % i !== 0) {
smallestCommon += max;
doneCalc = 0;
break;
}
else {
doneCalc = 1;
}
}
}
return smallestCommon;
}
Here is another nonrecursive for-loop solution
function smallestCommons(arr) {
var biggestNum = arr[0];
var smallestNum = arr[1];
var thirdNum;
//make sure biggestNum is always the largest
if (biggestNum < smallestNum) {
thirdNum = biggestNum;
biggestNum = smallestNum;
smallestNum = thirdNum;
}
var arrNum = [];
var count = 0;
var y = biggestNum;
// making array with all the numbers fom smallest to biggest
for (var i = smallestNum; i <= biggestNum; i += 1) {
arrNum.push(i);
}
for (var z = 0; z <= arrNum.length; z += 1) {
//noprotect
for (y; y < 10000000; y += 1) {
if (y % arrNum[z] === 0) {
count += 1;
break;
}
else if (count === arrNum.length) {
console.log(y);
return y;
}
else {
count = 0;
z = 0;
}
}
}
}
smallestCommons([23, 18]);
function smallestCommons(arr) {
var sortedArr = arr.sort(); // sort array first
var tempArr = []; // create an empty array to store the array range
var a = sortedArr[0];
var b = sortedArr[1];
for(var i = a; i <= b; i++){
tempArr.push(i);
}
// find the lcm of 2 nums using the Euclid's algorithm
function gcd(a, b){
while (b){
var temp = b;
b = a % b;
a = temp;
}
return a;
}
function lcm(a, b){
return Math.abs((a * b) / gcd(a, b));
}
var lcmRange = tempArr.reduce(lcm);
return lcmRange;
}
function smallestCommons(arr) {
let smallest, biggest, min;
arr.reduce(function (a, b) {
biggest = Math.max(a, b);
});
const max = biggest;
arr.reduce(function (a, b) {
smallest = Math.min(a, b);
min = smallest;
});
check: while (true) {
biggest += max;
for (min = smallest; min < max; min++) {
if (biggest % min != 0) {
continue check;
}
if (min == (max - 1) && biggest % min == 0) {
console.warn('found one');
return biggest;
}
}
}
}
function smallestCommons(arr) {
let min = Math.min(arr[0], arr[1]);
let max = Math.max(arr[0], arr[1]);
let scm = max;
//calc lcm of two numbers:a,b;
const calcLcm = function(a, b) {
let minValue = Math.min(a, b);
let maxValue = Math.max(a, b);
let lcm = maxValue;
while (lcm % minValue !== 0) {
lcm += maxValue;
}
return lcm;
}
//calc scm in range of arr;
for (let i = max; i >= min; i--) {
scm = calcLcm(scm, i);
}
console.log(scm);
return scm;
}
smallestCommons([1, 13]);
this is another very simple way and have low complexity.
function smallestCommons(arr) {
let smallestNum = arr[0] < arr[1] ? arr[0] : arr[1];
let greatestNum = arr[0] > arr[1] ? arr[0] : arr[1];
let initalsArr = [];
for(let i = smallestNum; i <= greatestNum; i++){
initalsArr.push(i);
}
let notFoundFlag = true;
let gNMltpl = 0;
let filteredArrLen;
while(notFoundFlag){
gNMltpl += greatestNum;
filteredArrLen = initalsArr.filter((num)=>{
return (gNMltpl / num) === Math.floor((gNMltpl / num))
}).length;
if(initalsArr.length == filteredArrLen){
notFoundFlag = false;
}
}
return gNMltpl;
}
My solution using es6 feature is
Lcm of given numbers
const gcd = (a, b) => (!b ? a : gcd(b, a % b));
const lcm = (a, b) => a * (b / gcd(a, b));
const getLcm = (arr) => {
const numbers = arr.sort((a, b) => parseInt(a) - parseInt(b));
let result = parseInt(numbers[0]);
for (let i = 1; i < numbers.length; i++) {
result = lcm(parseInt(result), parseInt(numbers[i + 1]));
}
return result;
};
Hcf of given numbers
const getHcf = (arr) => {
const numbers = arr.sort((a, b) => parseInt(a) - parseInt(b));
let result = parseInt(numbers[0]);
for (let i = 1; i < numbers.length; i++) {
result = gcd(parseInt(numbers[i]), parseInt(result));
}
return result;
};
Call like this
console.log(getLcm([20, 15, 10, 40])). Answer 120
console.log(getHcf([2, 4, 6, 8, 16])). Answer 2
I also found myself working on this challenge on my freeCodeCamp JavaScript Certification. This is what I have been able to come up with:
function smallestCommons(arr) {
let newArr = [];
// create a new array from arr [min, min + 1,......., max - 1, max]
for (let i = Math.min(...arr); i <= Math.max(...arr); i++){
newArr.push(i);
}
// let the max of newArr be the smallestCommonMultiple initially
let largest = Math.max(...newArr);
let smallestCommonMultiple = largest;
// If the supposedly smallestCommonMultiple fail on any of elements in
//newArr add the max element until we find the smallestCommonMultiple.
while (newArr.some(element => smallestCommonMultiple % element !== 0)){
smallestCommonMultiple += largest;
}
return smallestCommonMultiple;
}
console.log(smallestCommons([23, 18]));
i think it will work.
var a = [2, 6];
function getTotalX(a) {
var num = 1e15;
var i;
var arr = [];
for (i = 1; i <=num ; i++){
arr.push(i);
}
for (i = 0; i < a.length; i++){
var filterArr = arr.filter((val, ind, arr) => (val % a[i] === 0));
}
console.log(filterArr[0]); // will return 6
}
I've made a similar function in typescript that does the same task but only without recursion...
function findLowestCommonMultipleBetween(start: number, end: number): number {
let numbers: number[] = [];
for (let i = start; i <= end; i++) {
numbers.push(i);
}
for (let i = 1; true; i++) {
let divisor = end * i;
if (numbers.every((number) => divisor % number == 0)) {
return divisor;
}
}
}
function smallestCommons(arr) {
let min = Math.min(...arr);
let max = Math.max(...arr);
let rangArr = [];
for(let i = min; i <= max; i++) rangArr.push(i);
let smallestCommon = max;
while(!rangArr.every(e => smallestCommon % e === 0)){
smallestCommon += max;
}
return smallestCommon;
}
console.log(smallestCommons([1, 13]));
function smallestCommons(arr) {
arr = arr.sort((a, b) => a - b)
let range = []
for (let i = arr[0]; i <= arr[1]; i++) {
range.push(i)
}
for(let i = arr[1]; ; i++){
if(range.every((num => i % num == 0))){
return i
}
}
}
function smallestCommons(arr) {
// Kind of a brute force method, It's not fancy but it's very simple and easy to read :P
// make an array with all the numbers in the range.
let numbersArr = [];
for (let i = Math.min(...arr); i <= Math.max(...arr); i++) {
numbersArr.push(i);
}
// keep multiplying the biggest number until it's divisible by all the numbers in the numbersArr array.
let scm = Math.max(...arr);
while (true) {
if (numbersArr.every(num => scm % num === 0)) {
return scm;
} else {
scm += Math.max(...arr);
}
}
}
smallestCommons([2, 10]); // returns 2520.
smallestCommons([1, 13]); // returns 360360.
smallestCommons([23, 18]); // returns 6056820.
function leastCommonMultiple(arr) {
// Setup
const [min, max] = arr.sort((a, b) => a - b);
// Largest possible value for LCM
let upperBound = 1;
for (let i = min; i <= max; i++) {
upperBound *= i;
}
// Test all multiples of 'max'
for (let multiple = max; multiple <= upperBound; multiple += max) {
// Check if every value in range divides 'multiple'
let divisorCount = 0;
for (let i = min; i <= max; i++) {
// Count divisors
if (multiple % i === 0) {
divisorCount += 1;
}
}
if (divisorCount === max - min + 1) {
return multiple;
}
}
}
//for a test
leastCommonMultiple([1, 5]);
I am just starting JS, and understand the concept of finding a factor. However, this snippet of code is what I have so far. I have the str variable that outputs nothing but the first factor which is 2. I am trying to add each (int) to the str as a list of factors. What's the wrong in below code snippet?
function calculate(num) {
var str = "";
var int = 2;
if (num % int == 0) {
str = str + int;
int++;
} else {
int++;
}
alert(str);
}
calculate(232);
UPDATED ES6 version:
As #gengns suggested in the comments a simpler way to generate the array would be to use the spread operator and the keys method:
const factors = number => [...Array(number + 1).keys()].filter(i=>number % i === 0);
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
ES6 version:
const factors = number => Array
.from(Array(number + 1), (_, i) => i)
.filter(i => number % i === 0)
console.log(factors(36)); // [1, 2, 3, 4, 6, 9, 12, 18, 36]
https://jsfiddle.net/1bkpq17b/
Array(number) creates an empty array of [number] places
Array.from(arr, (_, i) => i) populates the empty array with values according to position [0,1,2,3,4,5,6,7,8,9]
.filter(i => ...) filters the populated [0,1,2,3,4,5] array to the elements which satisfy the condition of number % i === 0 which leaves only the numbers that are the factors of the original number.
Note that you can go just until Math.floor(number/2) for efficiency purposes if you deal with big numbers (or small).
As an even more performant complement to #the-quodesmith's answer, once you have a factor, you know immediately what its pairing product is:
function getFactors(num) {
const isEven = num % 2 === 0;
const max = Math.sqrt(num);
const inc = isEven ? 1 : 2;
let factors = [1, num];
for (let curFactor = isEven ? 2 : 3; curFactor <= max; curFactor += inc) {
if (num % curFactor !== 0) continue;
factors.push(curFactor);
let compliment = num / curFactor;
if (compliment !== curFactor) factors.push(compliment);
}
return factors;
}
for getFactors(300) this will run the loop only 15 times, as opposed to +-150 for the original.
#Moob's answer is correct. You must use a loop. However, you can speed up the process by determining if each number is even or odd. Odd numbers don't need to be checked against every number like evens do. Odd numbers can be checked against every-other number. Also, we don't need to check past half the given number as nothing above half will work. Excluding 0 and starting with 1:
function calculate(num) {
var half = Math.floor(num / 2), // Ensures a whole number <= num.
str = '1', // 1 will be a part of every solution.
i, j;
// Determine our increment value for the loop and starting point.
num % 2 === 0 ? (i = 2, j = 1) : (i = 3, j = 2);
for (i; i <= half; i += j) {
num % i === 0 ? str += ',' + i : false;
}
str += ',' + num; // Always include the original number.
console.log(str);
}
calculate(232);
http://jsfiddle.net/r8wh715t/
While I understand in your particular case (calculating 232) computation speed isn't a factor (<-- no pun intended), it could be an issue for larger numbers or multiple calculations. I was working on Project Euler problem #12 where I needed this type of function and computation speed was crucial.
function calculate(num) {
var str = "0";
for (var i = 1; i <= num; i++) {
if (num % i == 0) {
str += ',' + i;
}
}
alert(str);
}
calculate(232);
http://jsfiddle.net/67qmt/
Below is an implementation with the time complexity O(sqrt(N)):
function(A) {
var output = [];
for (var i=1; i <= Math.sqrt(A); i++) {
if (A % i === 0) {
output.push(i);
if (i !== Math.sqrt(A)) output.push(A/i);
}
}
if (output.indexOf(A) === -1) output.push(A);
return output;
}
here is a performance friendly version with complexity O(sqrt(N)).
Output is a sorted array without using sort.
var factors = (num) => {
let fac = [], i = 1, ind = 0;
while (i <= Math.floor(Math.sqrt(num))) {
//inserting new elements in the middle using splice
if (num%i === 0) {
fac.splice(ind,0,i);
if (i != num/i) {
fac.splice(-ind,0,num/i);
}
ind++;
}
i++;
}
//swapping first and last elements
let temp = fac[fac.length - 1];
fac[fac.length - 1] = fac[0];
fac[0] = temp;
// nice sorted array of factors
return fac;
};
console.log(factors(100));
Output:
[ 1, 2, 4, 5, 10, 20, 25, 50, 100 ]
This got me an 85% on Codility (Fails on the upperlimit, over a billion).
Reducing the input by half doesn't work well on large numbers as half is still a very large loop. So I used an object to keep track of the number and it's half value, meaning that we can reduce the loop to one quarter as we work from both ends simultaneously.
N=24 becomes: (1&24),(2&12),(3&8),(4&6)
function solution(N) {
const factors = {};
let num = 1;
let finished = false;
while(!finished)
{
if(factors[num] !== undefined)
{
finished = true;
}
else if(Number.isInteger(N/num))
{
factors[num] = 0;
factors[N/num]= 0;
}
num++
}
return Object.keys(factors).length;
}
Using generators in typescript in 2021
function* numberFactorGenerator(number: number): Generator<number> {
let i: number = 0;
while (i <= number) {
if (number % i === 0) {
yield i;
}
i++;
}
}
console.log([...numberFactorGenerator(12)]); // [ 1, 2, 3, 4, 6, 12 ]
function factorialize(num) {
var result = '';
if( num === 0){
return 1;
}else{
var myNum = [];
for(i = 1; i <= num; i++){
myNum.push(i);
result = myNum.reduce(function(pre,cur){
return pre * cur;
});
}
return result;
}
}
factorialize(9);
I came looking for an algorithm for this for use in factoring quadratic equations, meaning I need to consider both positive and negative numbers and factors. The below function does that and returns a list of factor pairs. Fiddle.
function getFactors(n) {
if (n === 0) {return "∞";} // Deal with 0
if (n % 1 !== 0) {return "The input must be an integer.";} // Deal with non-integers
// Check only up to the square root of the absolute value of n
// All factors above that will pair with factors below that
var absval_of_n = Math.abs(n),
sqrt_of_n = Math.sqrt(absval_of_n),
numbers_to_check = [];
for (var i=1; i <= sqrt_of_n; i++) {
numbers_to_check.push(i);
}
// Create an array of factor pairs
var factors = [];
for (var i=0; i <= numbers_to_check.length; i++) {
if (absval_of_n % i === 0) {
// Include both positive and negative factors
if (n>0) {
factors.push([i, absval_of_n/i]);
factors.push([-i, -absval_of_n/i]);
} else {
factors.push([-i, absval_of_n/i]);
factors.push([i, -absval_of_n/i]);
}
}
}
// Test for the console
console.log("FACTORS OF "+n+":\n"+
"There are "+factors.length+" factor pairs.");
for (var i=0; i<factors.length; i++) {
console.log(factors[i]);
}
return factors;
}
getFactors(-26);
function calculate(num){
var str = "0" // initializes a place holder for var str
for(i=2;i<num;i++){
var num2 = num%i;
if(num2 ==0){
str = str +i; // this line joins the factors to the var str
}
}
str1 = str.substr(1) //This removes the initial --var str = "0" at line 2
console.log(str1)
}
calculate(232);
//Output 2482958116
Here's an optimized solution using best practices, proper code style/readability, and returns the results in an ordered array.
function getFactors(num) {
const maxFactorNum = Math.floor(Math.sqrt(num));
const factorArr = [];
let count = 0; //count of factors found < maxFactorNum.
for (let i = 1; i <= maxFactorNum; i++) {
//inserting new elements in the middle using splice
if (num % i === 0) {
factorArr.splice(count, 0, i);
let otherFactor = num / i; //the other factor
if (i != otherFactor) {
//insert these factors in the front of the array
factorArr.splice(-count, 0, otherFactor);
}
count++;
}
}
//swapping first and last elements
let lastIndex = factorArr.length - 1;
let temp = factorArr[lastIndex];
factorArr[lastIndex] = factorArr[0];
factorArr[0] = temp;
return factorArr;
}
console.log(getFactors(100));
console.log(getFactors(240));
console.log(getFactors(600851475143)); //large number used in Project Euler.
I based my answer on the answer written by #Harman
We don't have to loop till end of the given number to find out all the factors. We just have to loop till reaching the given number's squareroot. After that point we, can figure out the rest of the factors by dividing the given number with the already found factors.
There is one special case with this logic. When the given number has a perfect square, then the middle factor is duplicated. The special case is also handled properly in the below code.
const findFactors = function (num) {
const startingFactors = []
const latterFactors = []
const sqrt = Math.sqrt(num)
for (let i = 1; i <= sqrt; i++) {
if (num % i == 0) {
startingFactors.push(i)
latterFactors.push(num / i)
}
}
// edge case (if number has perfect square, then the middle factor is replicated, so remove it)
if (sqrt % 1 == 0) startingFactors.pop()
return startingFactors.concat(latterFactors.reverse())
}
function factorialize(num) {
if(num === 0)
return 1;
var arr = [];
for(var i=1; i<= num; i++){
arr.push(i);
}
num = arr.reduce(function(preVal, curVal){
return preVal * curVal;
});
return num;
}
factorialize(5);