JavaScript (Find Minimum in Rotated Sorted Array) - javascript

I have a leetcode question that I tried to use my own method to solve it, but I got an error and I don't know what's wrong.
This is the topic:
This is my attempted solution:
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
findMin(nums.slice(start, end + 1));
};
findMin([3,4,5,1,2]);
and the output is undefined.
I tried this too :
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
findMin(nums.slice(start, end + 1));
return minEle;
};
findMin([3,4,5,1,2]);
And the output is 3.
I tried to debug it and I got this:
I don't understand why my recursion solution is not correct. Note that I tried to implement a solution with consideration of time complexity.

You are missing the last return statement when recursing.
return findMin(nums.slice(start, end + 1)); //added return here
var findMin = function(nums) {
if (nums.length === 0) return undefined;
var minEle = nums[0];
if (nums.length === 1) {
minEle = nums[0];
return minEle;
}
var start = 0;
var end = nums.length - 1;
if (nums[end] > nums[start]) {
end = Math.floor(end / 2);
} else {
start = Math.ceil(end / 2);
}
return findMin(nums.slice(start, end + 1));
};
console.log(findMin([3,4,5,1,2]));

If you want to find the smallest value in an array, just use Math.min.
Example:
console.log(Math.min.apply(null, [3,4,5,1,2]))

I don't think recursion is necessary for this one. At a high level we just need to go through each element and find the smallest. This could be done pretty simply with a for loop and a variable to store the smallest seen value.
var findMin = function(nums) {
if(nums.length === 0) {
return undefined;
}
if(nums.length === 1) {
return nums[0];
}
// initialize the smallest number placeholder to the first value
let smallestNum = nums[0];
for(let i = 1; i < nums.length; i++) {
if(smallestNum > nums[i]) {
smallestNum = nums[i];
}
}
return smallestNum;
}
This could be simplified with an array reducer, but the logic would be the same.
Another approach could be to assume the numbers will be ascending and once you find a number that is smaller return it. For example, in [3,4,5,1,2] it increases until we go from 5 to 1.
var findMin = function(nums) {
if(nums.length === 0) {
return undefined;
}
if(nums.length === 1) {
return nums[0];
}
for(let i = 1; i < nums.length; i++) {
if(nums[0] > nums[i]) {
return nums[i];
}
}
return nums[0];
}
In this case as soon as we find a number that is smaller than the first we break the loop. If we get all the way through the array we know the first number was the smallest.

I'm not at a rank to comment, so I have to post as an answer. It seems you're changing "end" and "start" in the if conditions, but then you're calling the function again and the function resets those variables to
var start = 0;
var end = nums.length - 1;
So whatever is changed in the second if/else statement, start will get reset to 0, and end will halve. But maybe I've missed something, so if this is irrelevant please ignore.

Related

Memoization giving less performance and taking more time

I was solving project euler in freecodecamp. When solving problem no 14 i use recursion and tried to increase the performance using memorization. But without memoization it is taking less time to execute and with memoization it is taking more time. Is memoization implementation is correct? What is wrong with this code? Can any one explain?
//Memoized version of the longestCollatzSequence project euler
let t1 = Date.now();
// function recurseWrapper(n) {
// let count = 0;
// let memo = {}
// function recurseCollatzSequence(n) {
// if (n in memo) {
// return memo[n];
// } else {
// if (n === 1) {
// return;
// } else if (n % 2 === 0) {
// count++;
// memo[n / 2] = recurseCollatzSequence((n / 2))
// } else {
// count++;
// memo[(3 * n) + 1] = recurseCollatzSequence(((3 * n) + 1))
// }
// return count
// }
// }
// return recurseCollatzSequence(n);
// }
//Without memoization (better performance)
function recurseWrapper(n) {
let count = 0;
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
return recurseCollatzSequence(n);
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.log(longestCollatzSequence(54512))
let t2 = Date.now() - t1;
console.log(`time taken by first instruction ${t2}`);
console.log(longestCollatzSequence(900000));
let t3 = Date.now() - t1 - t2
console.log(`time taken by second instruction ${t3}`);
let t4 = Date.now() - t1 - t2 - t3
console.log(longestCollatzSequence(1000000))
console.log(`time taken by third instruction ${t4}`);
From my limited understanding of the collatz conjecture, when starting at a number n, with all of the operations that you do, you should never see the same number again until you reach 1 (otherwise you would end up in an infinite loop). So your memo object will always hold unique keys that will never match the current number n, so if (n in memo) will never be true.
It actually seems that you want to memoize your results for further calls recurseWrapper() within your loop, so that you can prevent computing results you've already seen. At the moment you are not doing that, as you are creating a new memo object each time you call recurseWrapper(), removing all of the memoized values. You can instead return your inner auxiliary recursive wrapper function that closes over the memo object so that you keep the one memo object for all calls of the recursive wrapper function.
But even then we will still face issues, because of how the count is being calculated. For example, if you call recurseWrapper(n) and it takes 10 iterations to call recurseCollatzSequence(k), the returned count of recurseCollatzSequence(k) is going to be 10 plus whatever number it takes to compute the Collatz sequence for k. If we memoize this number, we can face issues. If we again call recurseWrapper on another number m, recurseWrapper(m), and this time it takes 20 iterations to get to the same call of recurseCollatzSequence(k), we will use our memoized value for k. But this value holds an additional count for the 10 that it took to get from n to k, and not just the count that it took to get from k to 1. As a result, we need to change how you're computing count in your recursive function so that it is pure, so that calling a function with the same arguments always produces the same result.
As Vincent also points out in a comment, you should be memoizing the current number, ie: memo[n] and not the number you're about to compute the Collatz count for (that memoization is done when you recurse):
function createCollatzCounter() {
const memo = {};
return function recurseCollatzSequence(n) {
if (n in memo) {
return memo[n];
} else {
if (n === 1) {
memo[n] = 0;
} else if (n % 2 === 0) {
memo[n] = 1 + recurseCollatzSequence(n / 2);
} else {
memo[n] = 1 + recurseCollatzSequence((3 * n) + 1);
}
return memo[n];
}
}
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
const recurseWrapper = createCollatzCounter();
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.time("First");
console.log(longestCollatzSequence(54512));
console.timeEnd("First");
console.time("Second");
console.log(longestCollatzSequence(900000));
console.timeEnd("Second");
console.time("Third");
console.log(longestCollatzSequence(1000000));
console.timeEnd("Third");
In comparison, the below shows times without memo:
//Without memoization (better performance)
function recurseWrapper(n) {
let count = 0;
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
return recurseCollatzSequence(n);
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.time("First");
console.log(longestCollatzSequence(54512))
console.timeEnd("First");
console.time("Second");
console.log(longestCollatzSequence(900000));
console.timeEnd("Second");
console.time("Third");
console.log(longestCollatzSequence(1000000));
console.timeEnd("Third");
Here is a streamlined version of the solution with minimal noise around memoization and recursion.
let memo = {};
function collatzSequence(n) {
if (! (n in memo)) {
if (n == 1) {
memo[n] = 1;
}
else if ((n % 2) === 0) {
memo[n] = 1 + collatzSequence(n/2);
} else {
memo[n] = 1 + collatzSequence(3*n + 1);
}
}
return memo[n];
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = collatzSequence(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
console.log(longestCollatzSequence(14))
And if you're willing to accept a bit of golf, here is a shorter version still of the first function.
let memo = {1: 1};
function collatzSequence(n) {
if (!(n in memo)) {
memo[n] = 1 + collatzSequence(0 === n%2 ? n/2 : 3*n+1);
}
return memo[n];
}
The reason why this matters has to do with how we think. As long as code reads naturally to us, how long it takes to write and think about it is directly correlated with how long it is. (This has been found to be true across a variety of languages in many places. I know that Software Estimation: Demystifying the Black Art certainly has it.) Therefore learning to think more efficiently about code will make it faster for you to write.
And that is why learning how to use techniques without talking about the technique you're using makes you better at that technique.
After spending some time figuring out I found a working solution.
The code below improved time complexity. Thanks all for helping me.
//Memoized version of the longestCollatzSequence project euler
let memo = {}
function recurseWrapper(n) {
let count = 0;
if (n in memo) {
return memo[n];
} else {
function recurseCollatzSequence(n) {
if (n === 1) {
return;
} else if (n % 2 === 0) {
count++;
recurseCollatzSequence((n / 2))
} else {
count++;
recurseCollatzSequence(((3 * n) + 1))
}
return count
}
let c = recurseCollatzSequence(n);
memo[n] = c;
return c;
}
}
function longestCollatzSequence(n) {
let max = 0;
let startNum = 0;
for (let i = n; i > 1; i--) {
let changeMax = recurseWrapper(i)
if (changeMax > max) {
max = changeMax;
startNum = i;
}
}
return startNum;
}
longestCollatzSequence(14)

Find First and Last Position of Element in Sorted Array in the order of O(log n)

I am doing leetcode #34
https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/
Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
Your algorithm's runtime complexity must be in the order of O(log n).
If the target is not found in the array, return [-1, -1].
Example 1:
Input: nums = [5,7,7,8,8,10], target = 8
Output: [3,4]
Example 2:
Input: nums = [5,7,7,8,8,10], target = 6
Output: [-1,-1]
var searchRange = function(nums, target) {
var result = [];
result[0] = findFirstIndex(nums, target);
result[1] = findLastIndex(nums, target);
return result;
};
//[5,7,7,8,8,10], target=10, midpoint=3
function findFirstIndex(nums, target) {
var index = -1; //if cant find, return index=-1, will not execute below action
var start = 0;
var end = nums.length - 1;
while (start <= end) {
var midPoint = start + (end - start) / 2;
if (nums[midPoint] >= target) {
end = midPoint - 1;
} else {
start = midPoint + 1;
}
if (nums[midPoint] === target) {
index = midPoint;
}
}
return index;
}
function findLastIndex(nums, target) {
var index = -1;
var start = 0;
var end = nums.length - 1;
while (start <= end) {
var midPoint = start + (end - start) / 2;
if (nums[midPoint] <= target) {
start = midPoint + 1; //[start,end]=[0,2]
} else {
end = midPoint - 1;
}
if (nums[midPoint] === target) {
index = midPoint;
}
}
return index;
}
Actually this answer I am reference Nick white 's method in Java way. I think the concept should be correct but still can not execute the answer.
Can anyone know why? Thanks.
You need to round midPoint down to an integer, otherwise you'll try to access fractional indexes.
var searchRange = function(nums, target) {
var result = [];
result[0] = findFirstIndex(nums, target);
result[1] = findLastIndex(nums, target);
return result;
};
console.log(searchRange([5,7,8,8,8,10], 8));
console.log(searchRange([5,7,8,8,8,10], 10));
function findFirstIndex(nums, target) {
var index = -1; //if cant find, return index=-1, will not execute below action
var start = 0;
var end = nums.length - 1;
while (start <= end) {
var midPoint = Math.floor(start + (end - start) / 2);
if (nums[midPoint] >= target) {
end = midPoint - 1;
} else {
start = midPoint + 1;
}
if (nums[midPoint] === target) {
index = midPoint;
}
}
return index;
}
function findLastIndex(nums, target) {
var index = -1;
var start = 0;
var end = nums.length - 1;
while (start <= end) {
var midPoint = Math.floor(start + (end - start) / 2);
if (nums[midPoint] <= target) {
start = midPoint + 1; //[start,end]=[0,2]
} else {
end = midPoint - 1;
}
if (nums[midPoint] === target) {
index = midPoint;
}
}
return index;
}
Actually there is no need for findLastIndex method. I modified a bit the solution of #Barmar.
var searchRange = function(nums, target) {
if(nums.length == 0) return [-1,-1];
var result = [];
var index = findFirstIndex(nums, target);
result[0] = index;
var value = nums[index];
while(nums[index] === value){index++}
result[1] = index - 1;
return result;
};
With this approach, I got 48 ms, faster than 96.65% of JavaScript online submissions.
It will not improve overall Big O complexity but surely it will improve average-case complexity.

How to find the least common multiple of a range of numbers?

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

Trying to find factors of a number in JS

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

determine if array is arithmetic or geometric progression (from Coderbyte)

Here is my functional code, as far as coderbyte is concerned.
But I have a feeling it shouldn't be this complicated.
Am I missing a simple trick?
function ArithGeo(arr)
{
var array_type = -1;
if (arr.length <= 2) return true;
var a = arr[1], r = a/arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a *= r) == arr[i]){
array_type = "Geometric";
}
else{
array_type = -1;
break;
}
}
if (array_type == "Geometric")
return array_type;
a = arr[1], d = a - arr[0], i;
for (i = 2; i < arr.length; ++i) {
if ((a += d) == arr[i]){
array_type = "Arithmetic";
}
else {
array_type = -1;
break;
}
}
return array_type;
}
ArithGeo([3,9,15,21,27, 28]);
function ArithGeo(arr) {
var diff = arr[1] - arr[0];
var ratio = arr[1] / arr[0];
var arith = true;
var geo = true;
for(var i = 0; i < arr.length - 1; i++)
{
if( arr[i + 1] - arr[i] !== diff )
arith = false;
if(arr[i + 1] / ratio !== arr[i])
geo = false;
}
if(arith === true)
return "arithmetic";
else if(geo === true)
return" geometric";
else
return -1;
}
Here's a simple solution as well. I'm either looking for a geometric pattern, where a given element will be divisible by the previous element, or an arithmetic pattern, where each element increases by a constant amount. Two variables, diff and ratio, contain each pattern to search for throughout the array.
I start by assuming that arith and geo are true, and if I find an example where one is not true, I set its value to false. Note that your code has two for loops, with the exact same conditions. This is a good indication that your code can be condensed into one loop.
With each pass through the loop, I test whether the conditions are present to set either arith or geo to false. Finally, after the loop exits, I will determine if either arith or geo remained true throughout the loop. If not, I return - 1 as the problem from Coderbyte requests.
edit: quick note on my for loop condition. Since I am checking the value of i + 1 with each pass, I make sure that I don't reach out of bounds by setting my exit condition to arr.length - 1. This way, i + 1 can still reach the last element, and will be sure not to overreach.
For arithmetic progression, subtract each element from previous element; their difference should be equal; for geometric, divide each element by the previous element, the ratio should stay the same. As for divide by zero when you meet 0, javascript gives you Inf (and it certainly is not a geometric progression). Because floats are inaccurate, maybe you'd want to store the min and max of these values and then see if they are close enough to each other.
function arithGeo(arr) {
var minRatio = 1/0,
maxRatio = -1/0,
minDiff = 1/0,
maxDiff = -1/0,
epsilon = 0.000001,
i,
ratio,
diff;
if (arr.length <= 2) {
return;
}
for (i = 1; i < arr.length; ++i) {
diff = arr[i] - arr[i - 1];
ratio = arr[i] / arr[i - 1];
minDiff = Math.min(diff, minDiff);
maxDiff = Math.max(diff, maxDiff);
minRatio = Math.min(ratio, minRatio);
maxRatio = Math.max(ratio, maxRatio);
}
if (Math.abs(minDiff - maxDiff) < epsilon) {
return "Arithmetic";
}
if (Math.abs(minRatio - maxRatio) < epsilon) {
return "Geometric";
}
return;
}
alert(arithGeo([3,9,15,21,27,28]));
alert(arithGeo([3,9,15,21,27]));
alert(arithGeo([4,2,1,0.5]));
It might not be the most efficient way to solve the problem, and it doesn't address the epsilon Problem, that Antti Haapala mentioned, but this is my solution to the problem:
function sequenceMatches(arr, fn) {
var compare = fn(arr[0], arr[1]);
for (var i = 2; i < arr.length; i++) {
if (fn(arr[i - 1], arr[i]) !== compare) return false;
}
return true;
}
function ArithGeo(arr) {
if (sequenceMatches(arr, function(a, b) { return b - a; })) return 'Arithemetic';
if (sequenceMatches(arr, function(a, b) { return b / a; })) return 'Geometric';
return -1;
}
I choose to solve that in two different functions, as that helps to clean up the code imho.
function ArithGeo(arr) {
var apCnt = 1;
var gpCnt = 1;
var diff = arr[1] - arr[0]; //ap difference
var div = arr[1]/arr[0]; //gp difference
for(var i=1;i<arr.length-1;i++){ //traverse array
if(arr[i+1] - arr[i] == diff) { //check for ap
apCnt+=1;
}
else if(arr[i+1]/arr[i] == div) { //check for gp
gpCnt+=1;
}
else{
break; //break if not ap or gp
}
}
return apCnt == arr.length-1 ? "Arithmetic": gpCnt == arr.length-1 ? "Geometric": -1; //return if its ap or gp
}
function ArithGeo(arr){
if(arr == null || !Array.isArray(arr)){
return "error";
}
var length = arr.length;
if(length === 0){
return "neither";
}
if(length === 1){
return "both";
}
var arithCount = 0,
geoCount = 0,
d = arr[1] - arr[0],
q = arr[1] / arr[0];
for(var i = length - 1; i > 0; i--){
if((arr[i] - arr[i-1]) === d){
arithCount++;
}
if((arr[i] / arr[i-1]) === q){
geoCount++;
}
}
if(arithCount === length - 1){
return "Arithmetic";
}else if (geoCount === length - 1){
return "Geometric";
}else if((arithCount === length - 1) && (geoCount === length - 1)){
return "both";
}else{
return "neither";
}
}
Sorry, only considered the integer sequence. #Antti Haapala's answer is correct.
Extremely late but I pretty much did the same on my own (novice javascript user).
It calculates the difference between i + 1 and i (or i + 1 / i) and pushes it into a new array. I then use a function to check if every element in the array is the same.
function numberCheck(array) {
var arithResult = null;
var geoResult = null;
var arithCounter = [];
var geoCounter = [];
Array.prototype.allValuesSame = function() {
for(var i = 1; i < this.length; i++) {
if(this[i] !== this[0])
return false;
} return true;
}
for (var b = 0; b < array.length - 1; b++) {
arithCounter.push(array[b + 1] - array[b]);
}
for (var i = 0; i < array.length - 1; i++) {
geoCounter.push(array[i + 1] / array[i])
}
arithResult = arithCounter.allValuesSame();
geoResult = geoCounter.allValuesSame();
if (arithResult === true) { return "Arithmetic";}
else if (geoResult === true) { return "Geometric";}
else { return "-1";}
}
numberCheck([1,2,4,8])

Categories