Mergesort is shaving off values in an array - javascript

I seem to have a basic mergesort working for small arrays but at larger n values it seems to be breaking & shaving off values. I'm testing using a helper function (largetest).
I've added conditionals for everything, verified the slices to be correct (to my understanding)
The helper function can assist in creating a large array, spotting points of difference (uncomment the console log), and verifying the lengths.
I've been running this on quokka.js in vscode.
var mergeSort = function(array) {
if (array.length === 1) {
return array;
}
const half = Math.floor(array.length / 2);
let left = array.slice(0, half);
let right = array.slice(half);
var joined = joinArrays(mergeSort(left), mergeSort(right));
return joined;
};
const joinArrays = (array1, array2) => {
var pointer1 = 0;
var pointer2 = 0;
let results = [];
while (array1[pointer1] && array2[pointer2]) {
if (array1[pointer1] <= array2[pointer2]) {
results.push(array1[pointer1]);
pointer1++;
} else if (array1[pointer1] > array2[pointer2]) {
results.push(array2[pointer2]);
pointer2++;
}
}
if (array1[pointer1]) {
results = results.concat(array1.slice(pointer1));
} else if (array2[pointer2]) {
results = results.concat(array2.slice(pointer2));
}
return results;
}
var a = mergeSort([4, 7, 4, 3, 9, 1, 2]);
console.log(a);
var a = mergeSort([48, 56, 2, 34, 98, 75, 42, 21, 3])
console.log(a);
var a = mergeSort([5, 6, 98324, 234, 34, 23, 42520, 234, 4323, 32])
console.log(a);
var a = mergeSort([4, 4, 4, 5, 7, 8, 9, 9, 1, 2, 3, ])
console.log(a);
function largeTest () {
var input = [];
var sorted;
var n = 10;
for (var i = 0; i < n; i++) {
var number = Math.floor(Math.random() * n);
input.push(number);
}
sorted = input.sort(function (a, b) {
return a - b;
});
var result = mergeSort(input);
console.log(result.length, sorted.length) //Why is it shaving numbers?
for (var i = 0; i < n; i++) {
if (result[i] !== sorted[i]) {
//console.log(i, 'result:', result[i], 'sorted:', sorted[i])
}
}
console.log('complete')
}
largeTest()

The heart of the problem lies in this line:
while (array1[pointer1] && array2[pointer2])
You should loop over both arrays and this loop does that as long as array values are not null, undefined or 0. It works because reading an array element beyond the end of the array returns undefined in javascript, hence tests false. The small arrays in your tests do not contain null values, so the code works, but larger arrays filled with pseudo-random data probably do, each causing the end of the corresponding slice to get shaved off.
You can fix this by testing the array length instead of the array contents:
const joinArrays = (array1, array2) => {
var pointer1 = 0, len1 = array1.length;
var pointer2 = 0, len2 = array2.length;
let results = [];
while (pointer1 < len1 && pointer2 < len2) {
if (array1[pointer1] <= array2[pointer2]) {
results.push(array1[pointer1]);
pointer1++;
} else {
results.push(array2[pointer2]);
pointer2++;
}
}
if (pointer1 < len1) {
results = results.concat(array1.slice(pointer1));
} else if (pointer2 < len2) {
results = results.concat(array2.slice(pointer2));
}
return results;
}

Your joinArrays() function looks awfully complicated for something as simple as merging two orders arrays. Try substituting a merge() function like this for your joinArrays() function:
function merge( left, right, compare = defaultComparer ) {
const merged = [];
let i = 0;
let j = 0;
let k = 0;
// ------------------------------------------------------
// while we have both a left and right item, just compare
// them and pick the lowest to put in the merged array
// ------------------------------------------------------
while ( i < left.length && j < right.length ) {
const cc = compare( left[i], right[j] );
merged[k++] = cc > 0 ? right[j++] : left[i++] ;
}
// ------------------------------------------------------
// if we only have left items... it's easy
// ------------------------------------------------------
while ( i < left.length ) {
merged[k++] = left[i++];
}
// ------------------------------------------------------
// if we only have right items... it's easy
// ------------------------------------------------------
while ( j < right.length ) {
merged[k++] = right[j++];
}
// ------------------------------------------------------
// return the merged array
// ------------------------------------------------------
return merged;
}
function defaultComparer( a, b ) {
return a < b ? -1
: a > b ? +1
: 0
;
}

Related

Javascript codewars : Tribonacci Sequence

function tribonacci(signature, n) {
var myArray = [];
var lenArray = 0;
var i = 0;
var outPut = 0;
var x = 0;
if (n > 0) {
while (i < 3) {
myArray.push(signature[i]);
i++;
}
lenArray = myArray.length - 1;
i = 0;
while (lenArray < n) {
while (x < 3) {
var v = x + i;
outPut += myArray[v];
x++;
}
i++;
lenArray = myArray.length - 1;
myArray.push(outPut);
}
return myArray;
} else {
return [];
};
}
console.log(tribonacci([1, 1, 1], 10));
First, I tried to push first 3 items into "myArray".
Second, in the "while" loop, while it's less than "n" (number of items needed to be in the array), add the last 3 items in "myArray" until "myArray" reaches the needed "n" amount.
e.g. tribonacci([1,1,1],10)
Return should be [1,1,1,3,5,9,17,31,57,105]
Adding the last 3 items continuously until it reaches 10 items in an array.
Instead I get as result:
[1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3]
I have no idea why it's stuck on 3s.
I tried "i++" below the 2nd "while" loop so that it can start adding the last 3 items every time "myArray" grows by one, but that doesn't seem to be the issue. Is the "outPut" being stuck on 3?
var v = x + i; uses x to calculate the correct index.
After adding those 3 numbers, x needs to be reset.
Also, outPut is reused in the next iteration, but it keeps adding values, so your output will get to high. This needs to be reset to 0 after the 3-loop.
Add outPut = x = 0 after pushing outPut into myArray
function tribonacci(signature, n) {
var myArray = [];
var lenArray = 0;
var i = 0;
var outPut = 0;
var x = 0;
if (n > 0) {
while (i < 3) {
myArray.push(signature[i]);
i++;
}
lenArray = myArray.length - 1;
i = 0;
while (lenArray < n) {
while (x < 3) {
var v = x + i;
outPut += myArray[v];
x++;
}
i++;
lenArray = myArray.length - 1;
myArray.push(outPut);
outPut = x = 0
}
return myArray;
} else {
return [];
};
}
console.log(tribonacci([1, 1, 1], 10));
[
1,
1,
1,
3,
5,
9,
17,
31,
57,
105,
193,
355
]
Some bonus-tips to improve the readabilty:
Use (...) spread operator to replace the first while:
var myArray = [ ...signature ];
Use myArray.length - 1 instead off defining a variable with the same value
Use myArray[x + i] instead off defining another varible
Return on n < 0 to you don't need to intent that much
Applying those will give:
function tribonacci(signature, n) {
var myArray = [ ...signature ];
var i = 0;
var x = 0;
var outPut = 0;
if (n < 0) {
return [];
}
while ((myArray.length - 1) < n) {
while (x < 3) {
outPut += myArray[x + i];
x++;
}
i++;
myArray.push(outPut);
outPut = x = 0;
}
return myArray;
}
Hey there are you doing this for homework on while loops? If so refer to #0stone0 's answer which solves it right!
If on the other hand you want to dive into JS a little more, I'd suggest you a more coincise solution with some cool Array function:
function tribonacci(signature, size) {
const output = signature;
while(output.length < size) {
output.push(output.slice(-3).sum());
}
return output;
}
console.log({ result: tribonacci([1, 1, 1], 10) });
Some version of JS don't include the Array.sum function which would be something like this:
Array.prototype.sum = function() {
return this.reduce((sum, curr) => sum + curr, 0);
}

Pushing strings onto the beginning and end of an array created during for loop

Right now I have for loop that is returning an array with the numbers 1 - 90, but am having trouble replacing the numbers 1 and 90 with the strings stored in my variables far and close (respectively).
const far = "01/01/20"
const close = "03/01/20"
const pushNinetyDays = () => {
let arr = [];
for (i = 1; i <= 90 ; i++) {
arr.push(i)
}
return arr
}
// => [1, 2, 3, 4,...89, 90]
I tried something along these lines for awhile, but wasn't getting the correct result.
const pushNinetyDays = () => {
let arr = [];
for (i = 1; i <= 90 ; i++) {
if (arr[i] === 1) {
arr.push(far)
} else if (arr[i] === 90) {
arr.push(close)
} else {
arr.push(i)
}
}
return arr
}
// still returning this array => [ 1, 2, 3, 4,...89,90]
// when i'm looking for this array => ["01,01,20", 2, 3, 4...89, "03/01/20"]
Can anyone help me out?
const pushNinetyDays = () => {
let arr = [];
for (i = 1; i <= 90 ; i++) {
if (i == 1) {
arr.push(far)
} else if (i == 90) {
arr.push(close)
} else {
arr.push(i)
}
}
return arr
}
All you had to do is check if i ==1 or 90 instead of what was in the array which was nothing. A better way would have been using the array and just setting arr[0] and arr[89].

Find the second largest number in array

I have an array of three element like [31,23,12] and I want to find the second largest element and its related position without rearranging the array.
Example :
array = [21,23,34]
Second_largest = 23;
Position is = 1;
Make a clone of your original array using .slice(0) like :
var temp_arr = arr.slice(0);
Then sor it so you get the second largest value at the index temp_arr.length - 2 of your array :
temp_arr.sort()[temp_arr.length - 2]
Now you could use indexOf() function to get the index of this value retrieved like :
arr.indexOf(second_largest_value);
var arr = [23, 21, 34, 34];
var temp_arr = [...new Set(arr)].slice(0); //clone array
var second_largest_value = temp_arr.sort()[temp_arr.length - 2];
var index_of_largest_value = arr.indexOf(second_largest_value);
console.log(second_largest_value);
console.log(index_of_largest_value);
Using ES6 Set and Array.from
const secondLargest = (arr) => Array.from([...new Set(arr)]).sort((a,b) => b-a)[1]
Above function removes duplicate elements using Set and returns the second largest element from the sorted array.
I tried to make the answer as simple as possible here, you can it super simple
function getSecondLargest(nums) {
var flarge = 0;
var slarge = 0;
for (var i = 0; i < nums.length; i++) {
if (flarge < nums[i]) {
slarge = flarge;
flarge = nums[i];
} else if (nums[i] > slarge) {
slarge = nums[i]
}
}
return slarge;
}
Its fully logical ,there is no array sort or reverse here, you can also use this when values are duplicate in aray.
function getSecondLargest(nums) {
nums.sort(function(x,y){
return y-x;
});
for(var j=1; j < nums.length; j++)
{
if(nums[j-1] !== nums[j])
{
return nums[j];
}
}
}
getSecondLargest([1,2,3,4,5,5]);
OUTPUT: 4
This method will also take care of the multiple occurrence of a number in the array. Here, we are first sorting the array and then ignoring the same number and returning our answer.
You could create a copy of the original array using spread and sort() it. From you'd just get the second to last number from the array and use indexOf to reveal it's index.
const array = [21,23,34];
const arrayCopy = [...array];
const secondLargestNum = arrayCopy.sort()[arrayCopy.length - 2]
console.log(array.indexOf(secondLargestNum));
Alternatively you can use concat to copy the array if compatibility is an issue:
var array = [21, 23, 34];
var arrayCopy = [].concat(array);
var secondLargestNum = arrayCopy.sort()[arrayCopy.length - 2]
console.log(array.indexOf(secondLargestNum));
This way is the most verbose, but also the most algorithmically efficient. It only requires 1 pass through the original array, does not require copying the array, nor sorting. It is also ES5 compliant, since you were asking about supportability.
var array = [21,23,34];
var res = array.reduce(function (results, curr, index) {
if (index === 0) {
results.largest = curr;
results.secondLargest = curr;
results.indexOfSecondLargest = 0;
results.indexOfLargest = 0;
}
else if (curr > results.secondLargest && curr <= results.largest) {
results.secondLargest = curr;
results.indexOfSecondLargest = index;
}
else if (curr > results.largest) {
results.secondLargest = results.largest;
results.largest = curr;
results.indexOfSecondLargest = results.indexOfLargest;
results.indexOfLargest = index;
}
return results;
}, {largest: -Infinity, secondLargest: -Infinity, indexOfLargest: -1, indexOfSecondLargest: -1});
console.log("Second Largest: ", res.secondLargest);
console.log("Index of Second Largest: ", res.indexOfSecondLargest);
I recently came across this problem, but wasn't allowed to use looping. I managed to get it working using recursion and since no one else suggested that possibility, I decided to post it here. :-)
let input = [29, 75, 12, 89, 103, 65, 100, 78, 115, 102, 55, 214]
const secondLargest = (arr, first = -Infinity, second = -Infinity, firstPos = -1, secondPos = -1, idx = 0) => {
arr = first === -Infinity ? [...arr] : arr;
const el = arr.shift();
if (!el) return { second, secondPos }
if (el > first) {
second = first;
secondPos = firstPos;
first = el;
firstPos = idx;
} if (el < first && el > second) {
second = el;
secondPos = idx;
}
return secondLargest(arr, first, second, firstPos, secondPos, ++idx);
}
console.log(secondLargest(input));
// {
// second: 115,
// secondPos: 8
// }
Hope this helps someone in my shoes some day.
Simple recursive function to find the n-largest number without permutating any array:
EDIT: Also works in case of multiple equal large numbers.
let array = [11,23,34];
let secondlargest = Max(array, 2);
let index = array.indexOf(secondlargest);
console.log("Number:", secondlargest ,"at position", index);
function Max(arr, nth = 1, max = Infinity) {
let large = -Infinity;
for(e of arr) {
if(e > large && e < max ) {
large = e;
} else if (max == large) {
nth++;
}
}
if(nth==0) return max;
return Max(arr, nth-1, large);
}
Just to get 2nd largest number-
arr = [21,23,34];
secondLargest = arr.slice(0).sort(function(a,b){return b-a})[1];
To get 2nd largest number with index in traditional manner-
arr = [20,120,111,215,54,78];
max = -Infinity;
max2 = -Infinity;
indexMax = -Infinity;
index2 = -Infinity;
for(let i=0; i<arr.length; i++) {
if(max < arr[i]) {
index2 = indexMax;
indexMax = i;
max2 = max;
max = arr[i];
} else if(max2 < arr[i]) {
index2 = i;
max2 = arr[i];
}
}
console.log(`index: ${index2} and max2: ${max2}`);
I have tried to solve without using the inbuilt function.
var arr = [1,2, -3, 15, 77, 12, 55];
var highest = 0, secondHighest = 0;
// OR var highest = arr[0], secondHighest = arr[0];
for(var i=0; i<arr.length; i++){
if(arr[i] > highest){
secondHighest = highest;
highest = arr[i];
}
if(arr[i] < highest && arr[i] > secondHighest){
secondHighest = arr[i];
}
}
console.log('>> highest number : ',highest); // 77
console.log('>> secondHighest number : ',secondHighest); // 55
var arr = [21,23,34];
var output = getSecondLargest(arr);
document.getElementById("output").innerHTML = output;
function getSecondLargest(nums) {
if (nums.length == 0){
return undefined;
}
nums.sort((a,b) => b-a);
var newArr = [...new Set(nums)];
return newArr[1];
}
<p id="output"></p>
function getSecondLargest(nums) {
const sortedArray = new Set(nums.sort((a, b) => b - a)).values();
sortedArray.next();
return sortedArray.next().value;
}
console.log(getSecondLargest([1, 2, 4, 4, 3]));
//Suggest making unique array before checking largest value in the array
function getSecondLargest(arr) {
let uniqueChars = [...new Set(arr)];
let val=Math.max(...uniqueChars);
let arr1 = arr.filter(function(item) {
return item !== val;
})
let num=Math.max(...arr1);
return num;
}
function main() {
const n = +(readLine());
const nums = readLine().split(' ').map(Number);
console.log(getSecondLargest(nums));
}
Here the code will give the second largest number and the index of it
const a = [1, 2, 3, 4, 6, 7, 7, 8, 15]
a.sort((a,b)=>a-b) //sorted small to large
const max = Math.max(...a)
const index = a.indexOf(max)
const s = {secondLargest:a[index-1],index:index-1}
console.log(s)
var elements = [21,23,34]
var largest = -Infinity
// Find largest
for (var i=0; i < elements.length; i++) {
if (elements[i] > largest) largest = elements[i]
}
var second_largest = -Infinity
var second_largest_position = -1
// Find second largest
for (var i=0; i < elements.length; i++) {
if (elements[i] > second_largest && elements[i] < largest) {
second_largest = elements[i]
second_largest_position = i
}
}
console.log(second_largest, second_largest_position)
function getSecondLargest(nums) {
let arr = nums.slice();//create a copy of the input array
let max = Math.max(...arr);//find the maximum element
let occ = 0;
for(var i = 0 ; i < arr.length ; i++)
{
if(arr[i] == max)
{
occ = occ +1;//count the occurrences of maximum element
}
}
let sortedArr =arr.sort(function(x, y) { return x > y; } );//sort the array
for(var i = 1 ; i <= occ ; i++){
sortedArr.pop()//remove the maximum elements from the sorted array
}
return Math.max(...sortedArr);//now find the largest to get the second largest
}
I write the most simple function with O(n) complexity using two variables max and secondMax with simple swapping logic.
function getSecondLargest(nums) {
let max = 0, secondMax = 0;
nums.forEach((num) => {
if (num > max) {
secondMax = max;
max = num;
} else if (num != max && num > secondMax) secondMax = num;
});
return secondMax;
}
here you can also deal with if the second largest or largest number is repeated
var nums =[2,3,6,6,5];
function getSecondLargest(nums) {
let secondlargets;
nums.sort(function(a, b){return a - b});
// all elements are in the accesindg order
// [1,2,3,5,6,6]
var highest;
// that is the last sorted element
highest = nums[nums.length-1];
nums.pop();
// through above statment we are removing the highest element
for(let i =0;i<nums.length-1;i++){
if(nums[nums.length-1]==highest){
/* here we remove gives this as conditon because might be the hiesht
had more indecis as we have in this question index(5) &index(6)
so remove the element till all positon have elemnt excepts the highest */
nums.pop()
}
else{
return nums[nums.length-1]
/* our array is already sorted and after removing thew highest element */
}
}
}
Please find a simple solution, without using inbuild functions:
Time complexity is O(n)
function secondLargest(arr) {
let prev = [0]
let i =1;
let largest =0;
while(i<arr.length){
let current = arr[i];
if(current > largest ) {
largest = current;
prev = arr[i-1];
} else if (current > prev && current < largest) {
prev = current
}
i++;
}
return prev;
}
let arr = [1,2,3,41,61,10,3,5,23];
console.log(secondLargest(arr));
Here is a simple solution using .sort() and new Set()
const array = [21, 23, 34, 34];
function getSecondLargest(arr){
return list = [...new Set(arr)].sort((a, b) => b - a)[1]
};
getSecondLargest(array);
In this case, if there are repeated numbers then they will be removed, and then will sort the array and find the second-largest number.
let arr=[12,13,42,34,34,21,42,39]
let uniqueArray=[...new Set(arr)]
let sortedArray=uniqueArray.sort((a,b)=>b-a)
console.log(sortedArray[1])
/* we can solve it with recursion*/
let count = 0; /* when find max then count ++ */
findSecondMax = (arr)=> {
let max = 0; /* when recursive function call again max will reinitialize and we get latest max */
arr.map((d,i)=>{
if(d > max) {
max = d;
}
if(i == arr.length -1) count++;
})
/* when count == 1 then we got out max so remove max from array and call recursively again with rest array so now count will give 2 here we go with 2nd max from array */
return count == 1 ? findSecondMax(arr.slice(0,arr.indexOf(max)).concat(arr.slice(arr.indexOf(max)+1))) : max;
}
console.log(findSecondMax([1,5,2,3]))
function getSecondLargest(nums) {
// Complete the function
var a = nums.sort();
var max = Math.max(...nums);
var rev = a.reverse();
for(var i = 0; i < nums.length; i++) {
if (rev[i] < max) {
return rev[i];
}
}
}
var nums = [2,3,6,6,5];
console.log( getSecondLargest(nums) );
Find Second Highest Number (Array contains duplicate values)
const getSecondHighestNumber = (numbersArry) => {
let maxNumber = Math.max( ...numbersArry);
let arrFiltered = numbersArry.filter(val => val != maxNumber);
return arrFiltered.length ? Math.max(...arrFiltered) : -1;
}
let items = ["6","2","4","5","5","5"];
const secondHighestVal = getSecondHighestNumber(items);
console.log(secondHighestVal); // 5
const arrData = [21, 23, 34];
const minArrValue = Math.min(...arrData);
const maxArrValue = Math.max(...arrData);
let targetHighValue = minArrValue;
let targetLowValue = maxArrValue;
for (i = 0; i < arrData.length; i++) {
if (arrData[i] < maxArrValue && arrData[i] > targetHighValue) {
targetHighValue = arrData[i];
}
if (arrData[i] > minArrValue && arrData[i] < targetLowValue) {
targetLowValue = arrData[i];
}
}
console.log('Array: [' + arrData + ']');
console.log('Low Value: ' + minArrValue);
console.log('2nd Lowest Value: ' + targetLowValue);
console.log('2nd Highest Value: ' + targetHighValue);
console.log('High Value: ' + maxArrValue);
Notice that if the max number appears multiple times in your array (like [6, 3,5,6,3,2,6]), you won't get the right output. So here is my solution:
function getSecondLargest(nums) {
// Complete the function
const sortedNumbers = nums.sort((a, b) => b - a);
const max = sortedNumbers[0];
const secondMax = sortedNumbers.find(number => number < max);
return secondMax;
}
const findSecondlargestNumber = (data) => {
let largest = null;
let secondlargest = null;
data.forEach(num => {
if(!largest) {
largest = num;
}
else if(num > largest) {
secondlargest = largest;
largest = num;
}
else if((!secondlargest && num !== largest) || (secondlargest)) {
secondlargest = num;
}
})
return secondlargest;
}
console.log(findSecondlargestNumber([11, 11, 3, 5, 6,2, 7]))
Here's the simplest way to get the second largest number and it's respective position from an array without rearranging the array or without using sorting method.
function findSecondLargest(arr) {
const largest = Math.max.apply(null, arr);
arr[arr.indexOf(largest)] = -Infinity;
const secondLargest = Math.max.apply(null, arr);
const position = arr.indexOf(secondLargest);
return { secondLargest, position };
}
console.log(findSecondLargest([3, 5, 7, 9, 11, 13])); //{ secondLargest: 11, position: 4 }
-Infinity is smaller than any negative finite number.
function getSecondLargest(nums) {
const len = nums.length;
const sort_arr = nums.sort();
var mynum = nums[len-1];
for(let i=len; i>0; i--){
if(mynum>nums[i-1]){
return nums[i-1];
}
}
}

Javascript least common multiple algorithm

I'm trying to script a function that takes two numbers and returns the smallest common multiple that is also divisible by all the numbers between those numbers, what I've got only works for 1,1 through 1,12, but for some reason stops working at 1,13. Other set like 12,14 work but I can't figure out why or what the pattern is.
function smallestCommons(arr) {
arr.sort(function(a, b) {
return a-b;
});
var arr1 = [];
var arr2 = [];
for (var k = arr[0]; k<=arr[1]; k++) {
arr1.push(k);
}
function remainder(val1, val2) {
return val1%val2;
}
var b = arr1.reduce(function(a, b) {
return a*b;
});
var i = arr1[arr1.length-1]*arr1[arr1.length-2];
while (i<=b) {
for (var m = 0; m<arr1.length; m++) {
var a = remainder(i, arr1[m]);
arr2.push(a);
}
var answer = arr2.reduce(function(c, d) {
return c+d;
});
if (answer === 0) {
return i;
} else {
arr2 = [];
i++;
}
}
}
I guess you can do as follows in JavaScript; It can calculate the common LCM up to an 216 item array, such as [1,2,3,...,216] in less than 0.25 ms.
function gcd(a,b){
var t = 0;
a < b && (t = b, b = a, a = t); // swap them if a < b
t = a%b;
return t ? gcd(b,t) : b;
}
function lcm(a,b){
return a/gcd(a,b)*b;
}
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13],
brr = Array(216).fill().map((_,i) => i+1), // limit before Infinity
result = arr.reduce(lcm);
console.log(result);
console.time("limit");
result = brr.reduce(lcm);
console.timeEnd("limit");
console.log(result);
A way is to keep multiplying the largest number in your range with an increasing number and check if all the others are divisible by that. If yes, return that or continue the loop.
Here is my solution in typescript...
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;
}
}
}
...but for larger ranges, this is a more efficient answer :)
As far as I can tell your algorithm is giving you a correct answer.
I am far from being a professional programmer so anyone who wants please give options to improve my code or its style :)
If you want to be able to check for the answer yourself you can check this fiddle:
https://jsfiddle.net/cowCrazy/Ld8khrx7/
function multiplyDict(arr) {
arr.sort(function (a, b) {
return a - b;
});
if (arr[0] === 1) {
arr[0] = 2;
}
var currentArr = [];
for (var i = arr[0]; i <= arr[1]; i++) {
currentArr.push(i);
}
var primeDivs = allPrimes(arr[1]);
var divsDict = {};
for (var j = currentArr[0]; j <= currentArr[currentArr.length -1]; j++){
divsDict[j] = [];
if (primeDivs.indexOf(j) > -1) {
divsDict[j].push(j);
} else {
var x = j;
for (var n = 2; n <= Math.floor(j / 2); n++) {
if (x % n === 0) {
divsDict[j].push(n);
x = x / n;
n--;
continue;
}
}
}
}
return divsDict;
}
function allPrimes(num) {
var primeArr = [];
var smallestDiv = 2;
loopi:
for (var i = 2; i <= num; i++) {
loopj:
for (var j = smallestDiv; j <= largestDiv(i); j++) {
if (i % j === 0) {
continue loopi;
}
}
primeArr.push(i);
}
return primeArr;
}
function largestDiv (a) {
return Math.floor(Math.sqrt(a));
}
multiplyDict([1,13]);
it gives a dictionary of the requested array and the divisors of each element.
from there you can go on your own to check that your algorithm is doing the right job or you can check it here:
https://jsfiddle.net/cowCrazy/kr04mas7/
I hope it helps
It is true! The result of [1, 13] is 360360. and after this we have [1, 14].
14 = 2 * 7 and we now 360360 is dividable to 2 and 7 so the answer is 360360 again.
[1, 15]: 15 = 3 * 5 and result is same.
[1, 16]: result is 720720.
[1, 17]: result is: 12252240
[1, 18]: 18 = 2 * 9 and result is 12252240 same as 17
[1, 19]: for my computer this process is so heavy and can not do this. But in a strong machine it will work. I promise. But your code is not good in performance.
To find the LCM in N numbers.
It is Compatible with ES6, and consider that is there is no control for boundaries in case that we need to find for large numbers.
var a = [10, 40, 50, 7];
console.log(GetMinMultiple(a));
function GetMinMultiple(data) {
var maxOf = data.reduce((max, p) => p > max ? p : max, 0);
var incremental = maxOf;
var found = false;
do {
for (var j = 0; j < data.length; j++) {
if (maxOf % data[j] !== 0) {
maxOf += incremental;
break;
}
else {
if (j === data.length - 1) {
found = true;
break;
}
}
}
} while (!found);
return maxOf;
}
https://jsfiddle.net/djp30gfz/
Here is my solution in Typescript
function greatestCommonDivider(x: number, y: number): number {
if (y === 0) {
return x;
}
return greatestCommonDivider(y, x % y);
}
function singleLowestCommonMultiply(x: number, y: number): number {
return (x * y) / greatestCommonDivider(x, y);
}
function lowestCommonMultiply(...numbers: number[]): number {
/**
* For each number, get it's lowest common multiply with next number.
*
* Then using new number, compute new lowest common multiply
*/
return numbers.reduce((a, b) => {
return singleLowestCommonMultiply(a, b);
});
}
lowestCommonMultiply(2, 3); // Outputs 6
lowestCommonMultiply(2, 3, 5); // Outputs 30
Playground - click here

Get elements that has no double value in an array

I have a question . How do you retrieve elements that has no double value in an array?? For example: [1,1,2,2,3,4,4,5] then you retrieve [3,5] only.
Thanks in advance
for (var j = 0; j < newArr.length; j++) {
if ((arr1.indexOf(newArr[j]) === 0) && (arr2.indexOf(newArr[j]) === 0)) {
index = newArr.indexOf(j); newArr.splice(index, 1);
}
}
If the item in the array is unique then the index found from the beginning should equal the index found from the end, in other words:
var xs = [1, 1, 2, 2, 3, 4, 4, 5];
var result = xs.filter(function(x) {
return xs.indexOf(x) === xs.lastIndexOf(x);
});
console.log(result); //=> [3, 5]
sorry for the presentation its my first post !
You have to compare each element of your array to the others in order to get the number of occurence of each element
var tab = [1,1,2,2,3,4,4,5] //The array to analyze
tab = tab.sort(); // we sort the array
show(tab); // we display the array to the console (F12 to open it)
var uniqueElementTab = []; // this array will contain all single occurence
var sameElementCounter = 0;
for(x=0;x<tab.length;x++){ // for all element in the array
sameElementCounter = 0;
for(y=0;y<tab.length;y++){ // we compare it to the others
if((tab[x]==tab[y])){
sameElementCounter+=1; // +1 each time we meet the element elsewhere
}
}
if(sameElementCounter<=1){
uniqueElementTab.push(tab[x]); //if the element is unique we add it to a new array
}
}
show(uniqueElementTab); // display result
function show(tab) { // Simple function to display the content of an array
var st="";
for(i=0;i<tab.length;i++){
st += tab[i]+" ";
}
console.log(st+"\n");
}
Hope it helps.
Here is a simple "tricky" solution using Array.sort, Array.join, Array.map, String.replace and String.split functions:
var arr = [1, 1, 2, 2, 3, 4, 4, 5];
arr.sort();
var unique = arr.join("").replace(/(\d)\1+/g, "").split("").map(Number);
console.log(unique); // [3, 5]
create new array tmp,and check already value exist by indexOf .If existed delete by splice function..
var arr = [1,1,2,2,3,4,4,5];
var tmp = [];
var dup = [];
for(var i = 0; i < arr.length; i++){
var ind = tmp.indexOf(arr[i]);
if(ind == -1){
if(dup.indexOf(arr[i]) == -1){
tmp.push(arr[i]);
}
}
else{
tmp.splice(ind,1);
dup.push(arr[i]);
}
}
console.log(tmp);
This would be my way of doing this job.
var arr = [1,1,2,2,3,4,4,5],
uniques = Object.keys(arr.reduce((p,c) => (c in p ? Object.defineProperty(p, c, {enumerable : false,
writable : true,
configurable : true})
: p[c] = c,
p), {}));
console.log(uniques);
A solution for unsorted arrays with a hash table for the items. Complexity O(2n)
var array = [1, 1, 2, 2, 3, 4, 4, 5, 1],
hash = Object.create(null),
single;
array.forEach(function (a, i) {
hash[a] = a in hash ? -1 : i;
});
single = array.filter(function (a, i) {
return hash[a] === i;
});
console.log(single);
If the array is sorted, you can solve this in O(n) (see "pushUniqueSinglePass" below):
function pushUniqueSinglePass(array, unique) {
var prev; // last element seen
var run = 0; // number of times it has been seen
for (var i = 0; i < array.length; i++) {
if (array[i] != prev) {
if (run == 1) {
unique.push(prev); // "prev" appears only once
}
prev = array[i];
run = 1;
} else {
run++;
}
}
}
function pushUniqueWithSet(array, unique) {
var set = new Set();
for (var i = 0; i < array.length; i++) {
set.add(array[i]);
}
for (let e of set) {
unique.push(set);
}
}
// Utility and test functions
function randomSortedArray(n, max) {
var array = [];
for (var i = 0; i < n; i++) {
array.push(Math.floor(max * Math.random()));
}
return array.sort();
}
function runtest(i) {
var array = randomSortedArray(i, i / 2);
var r1 = [],
r2 = [];
console.log("Size: " + i);
console.log("Single-pass: " + time(
pushUniqueSinglePass, array, r1));
console.log("With set: " + time(
pushUniqueWithSet, array, r2));
// missing - assert r1 == r2
}
[10, 100, 1000, 10000,
100000, 1000000
].forEach(runtest);
function time(fun, array, unique) {
var start = new Date().getTime();
fun(array, unique);
return new Date().getTime() - start;
}
This is much more efficient than using maps or sorting (time it!). In my machine, a 1M sorted array can have its unique elements found in 18 ms; while the version that uses a set requires 10x more.

Categories