How to find prime numbers in an array? - javascript

My goal here is to find the prime numbers:
let arr = [2, 3, 4, 6, 9, 10, 11, 15];
let ret = [];
arr.filter((z, ind) => {
if (ind > 0) {
ret.every(x => {
!Number.isInteger(z / x) ? ret.push(z) : false;
});
} else {
ret.push(z);
}
});
console.log(ret); // should be: [2,3,11]
It works for even numbers, but it doesn't work for the odd.

Fixed your code:
let arr = [2,3,4,6,9,10,11,15]
let ret = [];
arr.filter((z, ind) => {
if(ind > 0){
if(ret.every( x => !Number.isInteger(z/x)) ){
ret.push(z)
}
} else { ret.push(z) }
})
console.log(ret)

The Array.filter() method returns an array, so no need to generate the array by pushing the elements to an external array.
The prime check is easier with a for loop. Check that the number doesn't produce an integer if divided by all the numbers between 2 and half its size (rounded down). We need to check all half way, because every number that is greater than half the number we are checking, would produce a result that is less than 2, and 2 is the smallest integer divisor of a number.
const arr = [2, 3, 4, 6, 9, 10, 11, 15];
const isPrime = num => {
if(num < 4) return true; // 1, 2, 3 are prime numbers
const div = Math.floor(num / 2); // the max number to use as divider
for(let i = 2; i <= div; i++) {
if(Number.isInteger(num / i)) return false; // if the result is an integer, it's not a prime number
}
return true; // it's a prime number
};
const result = arr.filter(isPrime);
console.log(result); // should be: [2,3,11]

Related

Find indexes of the biggest and lowest numbers in array

I need to create a function which finds the two numbers with the largest difference between them and returns their indices as an array of two elements - [ lowest, biggest ].
Notice: the bigger number must be to the right from lowest. If we have no difference between the numbers, the function must return [].
function getProfit(arr) {
let result = [];
let sortedArr = arr.sort();
let min = sortedArr.indexOf(Math.min(...sortedArr));
let max = sortedArr.indexOf(Math.max(...sortedArr));
if(max > min) {
result.push(min);
result.push(max);
return result;
} else {
return [];
}
}
console.log(getProfit([13, 6, 3, 4, 10, 2, 3], [2, 4]));
You need to iterate through the list with two pointers (indexes) left and right as described below:
you will accomplish your solution with time complexity of O(n).
function getProfit(arr) {
let result = [0,0];
for(let l=0,r=0; l<arr.length-1 && r<arr.length-1;r++){
if(arr[l] > arr[r]){
l++;
}else if(arr[r]-arr[l]> arr[result[1]]-arr[result[0]]){
result[0] = l;
result[1] = r;
}
}
return (result[1] === 0) ? [] : result;
}
console.log(getProfit([13, 6, 3, 4, 10, 2, 3]));

return "even" if others numbers are odd and "odd" the others number are even javascript

I have 2 questions, how can I get value instead of value inside array and how can I make this code shorter and declarative.
arr = [16, 4, 11, 20, 2]
arrP = [7, 4, 11, 3, 41]
arrTest = [2, 4, 0, 100, 4, 7, 2602, 36]
function findOutlier(arr) {
const isPair = (num) => num % 2 === 0
countEven = 0
countOdd = 0
arr1 = []
arr2 = []
const result = arr.filter((ele, i) => {
if (isPair(ele)) {
countEven++
arr1.push(ele)
} else {
countOdd++
arr2.push(ele)
}
})
return countEven > countOdd ? arr2 : arr1
}
console.log(findOutlier(arrTest))
Filtering twice may be more readable.
even = arr.filter((x) => x % 2 == 0);
odd = arr.filter((x) => x % 2 == 1);
if (even.length > odd.length) {
return even;
} else {
return odd;
}
If you're looking to do this with one loop, consider using the array reduce method to put each number into an even or odd bucket, and then compare the length of those buckets in your return:
function findOutlier(arr) {
const sorted = arr.reduce((acc, el) => {
acc[el % 2].push(el);
return acc;
},{ 0: [], 1: [] })
return sorted[0].length > sorted[1].length ? sorted[1] : sorted[0];
}
const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(findOutlier(arr));
Note that this does not handle when the arrays are the same length gracefully (right now it'll just return the odd array).
You could take an object with the wanted part for collecting and add a short circuit if one of the types has a count of one and the others have a count greater than one.
const
isPair = num => num % 2 === 0,
findOutlier = array => {
count = { true: [], false: [] };
for (const value of array) {
count[isPair(value)].push(value);
if (count.true.length === 1 && count.false.length > 1) return count.true[0];
if (count.false.length === 1 && count.true.length > 1) return count.false[0];
}
};
console.log(...[[16, 4, 11, 20, 2], [7, 4, 11, 3, 41], [2, 4, 0, 100, 4, 7, 2602, 36]].map(findOutlier));
Here is an solution that selects the even or odd array based on the modulo result.
function findOutlier(integers) {
const even = [], odd = [], modulos = [even, odd];
for (const integer of integers) {
modulos[Math.abs(integer % 2)].push(integer);
}
return even.length > odd.length ? odd : even;
}
console.log(findOutlier([2, 4, 0, 100, 4, 7, 2602, 36]));
You unfortunately do need Math.abs() to handle negative values, because -3 % 2 == -1.
See: JavaScript % (modulo) gives a negative result for negative numbers
However the name findOutlier lets me assume there is only a single outlier within the provided list. If this is the case you can optimize the algorithm.
function findOutlier(integers) {
// With less than 3 integers there can be no outlier.
if (integers.length < 3) return;
const isEven = (integer) => integer % 2 == 0;
const isOdd = (integer) => !isEven(integer);
// Determine the outlire based on the first 3 elements.
// If there are 0 or 1 integers even, the outlire is even.
// if there are 2 or 3 integers even, the outlier is odd.
const outlier = integers.slice(0, 3).filter(isEven).length < 2
? isEven
: isOdd;
return integers.find(outlier);
}
console.log(findOutlier([2, 4, 0, 100, 4, 7, 2602, 36]));
You can do this without creating intermediate arrays by simply comparing each element to its neighbors and returning that element if it is different to both, or undefined if no outliers are found. This returns in the same iteration in which the outlier is first encountered, and returns the value itself and not an array.
function findOutlier(array) {
const
len = array.length,
isEven = (n) => n % 2 === 0;
for (const [i, value] of array.entries()) {
let
prev = array[(i-1+len)%len], // loop around if < 0 (first element)
next = array[(i+1)%len]; // loop around if >= length (last element)
if (isEven(value) !== isEven(prev) && isEven(value) !== isEven(next)) {
return value;
}
}
return undefined;
}
const arrays = [[16, 4, 11, 20, 2], [7, 4, 11, 3, 41], [2, 4, 0, 100, 4, 7, 2602, 36]]
console.log(...arrays.map(findOutlier));
Now that OP clarified the requirements (at least in a comment) this allows a different approach:
function findOutlier(array) {
let odd = undefined, even = undefined;
for (let i of array) {
let isEven = i % 2 == 0;
if (odd !== undefined && even !== undefined)
return isEven ? odd : even;
if (isEven) even = i;
else odd = i;
}
if (odd !== undefined && even !== undefined)
return array[array.length-1];
}
console.log(findOutlier([2,4,6,8,10,5]))
The algorithm will iterate the array, and store the lastest found odd and even numbers, respectively.
If we discovered both an odd and an even number already, with the current number we can decide, which of them is the outlier: If the current number is even, it's at least the second even number we found. Thus, the found odd number must be the outlier. The same applies vice versa if the current number is odd. The special case, if the outlier is the last element of the array, is checked with an additional condition after the loop.
If all numbers are odd or even (ie there is no outlier) this function will return undefined. This algorithm does not throw an error, if the preconditions are not met, ie if there is more than one outlier.

Chunking an array by value with odds and evens

I'm trying to create a function that groups an array of numbers based on a length parameter. The length represents the max length of each sub-array. The code works as it is meant to for getting the sub arrays, but what I'd like to do is make it sort by odd and even.
function myFunctionA(myArr1, myVal) {
newArr = [];
for ( x = 0; x < myArr1.length; x += myVal) {
newArr.push(myArr1.slice(x, x + myVal));
}
return newArr;
}
Console.log(myfunction([1,2,3,4,5,6,7,8,9,10],3))
This returns [[1,2,3],[4,5,6],[7,8,9],[10]]
What I'd like to do is go through each sub array at a time until the sub arrays are the correct length and add any leftover values to a sub array/s
This would look like
[[1,3,5][2,4,6][7,9][8,10]]
Since arr 0 and arr 1 are the correct length that we have stated in the console.log statement, 7 8 9 and 10 are left over. But since the can't create a full sub array and they are odds and even, they form two sub arrays with a side of 2.
Other examples:
myfunction([1,2,3,4,5,6,7],2)
Should return [[1,3],[2,4],[5,7],[6]]
myfunction([1,2,3,4,5,6,7,8],1)
Should return [[1][2][3][4][5][6][7][8]]
You could take an array for collecting all odd and even values and then push the group if it has zero items. By having the wanted size, create a new array.
function chunkenator(array, size, fn) {
let groups = [],
result = [];
for (let value of array) {
const group = fn(value);
if (!groups[group]) groups[group] = [];
if (!groups[group].length) result.push(groups[group]);
groups[group].push(value);
if (groups[group].length === size) groups[group] = [];
}
return result;
}
console.log(chunkenator([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3, x => x % 2));
console.log(chunkenator([1, 3, 5, 7, 8, 9, 11, 13, 15], 3, x => x % 2));
One possibility would be to first seperate the numbers into even and odd numbers and then just loop over it, pushing the numbers into a new array switching between even and odd numbers.
It's not the cleanest piece of code, but it works.
function myfunction(arr, n) {
const evenOdd = arr.reduce((acc, e) => {
const ind = +(e % 2 === 0);
acc[ind] = acc[ind] || [];
acc[ind].push(e);
return acc;
}, []);
let ind = 0, res = [[]];
while (evenOdd[0].length || evenOdd[1].length) {
for (let i = n; i--;) {
const val = evenOdd[ind].shift();
if (val) res[res.length - 1].push(val)
}
ind = (ind + 1) % 2
res.push([])
}
res.pop()
return res;
}
for (const n of [1, 2, 3]) {
console.log(n,
myfunction([1, 2, 3, 4, 5, 6, 7, 8], n)
)
}

Array of numbers to batches of given sum

I've a JavaScript array and sum as input
array = [4,8,2,4,2,2,8,12,4,2, 2]
sum = 12 // all the time sum will be 12
I want 2d array, the numbers in batches should be sum equals or less than 12
The output array should look like
[
[4,8],
[2,4,2,2,2],
[8, 4],
[12],
[2]
]
4 + 8 = 12
2 + 4 + 2 + 2 + 2 = 12
...
2 is left at the end
Other examples
1) array = [6,5,3,3,3,2,2,2,2]
sum = 12
output: [ [6,3,3], [5,3,2,2], [2,2] ]
One the number is allotted to subset, it should not used to other subset
remaining numbers can be added to the last but sum should be less than 12, else add one more array and add remaining ones
The input array can have any integer from 1 - 12
How can I get the output I want?
Try this function. I commented the code as much as possible to clarify it.
const example1 = [4, 8, 2, 4, 2, 2, 8, 12, 4, 2, 2];
const example2 = [6, 5, 3, 3, 3, 2, 2, 2, 2];
const example3 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
const example4 = [5,12,3,4,4,1,1,1,5,8,12,6,9,11,6];
const example5 = [4, 2, 1, 2, 3, 3, 5, 7, 8, 9];
const lookAhead = function(array, searchFor) {
return array.some(val => {
return val <= searchFor;
});
}
function findPairs(inputArray) {
// First sort array in descending order
inputArray.sort((a, b) => b - a);
console.log("input", JSON.stringify(inputArray.slice(0)));
// set variables
const pairArray = [];
const max = 12;
inputArray.forEach(function(num, index) {
// when looping the array we will replace values with null once completed,
// Therefore if value is null no need to go futher
if (num == null)
return;
// initiate pair value with current number
const pair = [num];
// set it to null in input array
inputArray[index] = null;
// if number equals to max (ie. 12) no need to go futher
if (num == max) {
pairArray.push(pair);
return;
}
let total = num;
// Loop through array again to see matching numbers
for (let i = 0; i < inputArray.length; i++) {
// Don't go futher if it is a null value
if (inputArray[i] == null)
continue;
const add = total + inputArray[i];
/* if the total is less than max (12) then we check if we have an edge case
* For example in an array like [6, 5, 3, 3, 3], 6 + 5 is 11 but in next loops we
* will not find any "1" to get to 12. Therefore we escape this iteration and check
* next numbers. In this case the result would be 6 + 3 + 3
*/
if (add < max) {
const found = lookAhead(inputArray.slice(i), max - add);
if (found) {
pair.push(inputArray[i]);
total = add;
inputArray[i] = null;
}
} else if (add == max) {
// The addition is equals to max. Push the number and set it to null in input array
pair.push(inputArray[i]);
inputArray[i] = null;
total = 0;
break;
}
}
// Push pair array from this iteration to pairArray
pairArray.push(pair);
});
console.log("output", JSON.stringify(pairArray));
console.log("-------");
}
findPairs(example1);
findPairs(example2);
findPairs(example3);
findPairs(example4);
findPairs(example5);
A little complex to understand but here you go...
let originalArray = [7, 7, 7, 7, 7]
let sum = 12;
let twoDiArray = [];
let CalculateSum = (array, element) => {
array = [...array, element]
return array.reduce((x, y) => {
return x + y;
})
}
twoDiArray.push([]);
originalArray.forEach(element => {
for (let i = 0; i < twoDiArray.length; i++) {
if (CalculateSum(twoDiArray[i], element) <= 12) {
twoDiArray[i].push(element);
break;
} else {
if (twoDiArray.length - 1 === i) {
twoDiArray.push([element]);
break;
}
}
}
})
console.log(twoDiArray)
Here you... I will keep both answers open for future use of others...
let originalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
let sum = 12;
let twoDiArray = [];
let CalculateSum = (array, element) => {
array = [...array, element]
return array.reduce((x, y) => {
return x + y;
})
}
twoDiArray.push([originalArray[0]]);
originalArray.splice(0, 1);
do {
originalArray.forEach((element, index) => {
for (let i = 0; i < twoDiArray.length; i++) {
let summ = CalculateSum(twoDiArray[i], element);
if (summ === 12) {
twoDiArray[i].push(element);
originalArray.splice(index, 1);
break;
} else {
if (index === originalArray.length - 1) {
if (CalculateSum(twoDiArray[twoDiArray.length - 1], originalArray[0]) <= 12) {
twoDiArray[twoDiArray.length - 1].push(originalArray[0]);
break;
} else {
twoDiArray.push([originalArray[0]]);
}
originalArray.splice(0, 1);
}
}
}
})
}
while (originalArray.length > 0);
console.log(twoDiArray)

Get the sum of array items that are equal to the target (Subset sum)

I need to get the sum of array items that are equal to the target. If the sum of array item will not equal to the target I would like to get the highest sum that is less than the target.
Here is an example:
Input: [4, 6, 8, 12, 4, 6, 6, 12, 4, 4,4]
Results:
[12]
[12]
[8, 4]
[6, 6]
[4,4,4]
[6,4]
Note: The array item can only be used once.
Currently here is what I have right now:
var subset_sum = function (items, target) {
var results = [];
items.sort(function (a, b) { return b - a });
ss = function (items) {
var item = items.shift();
if (item < target) {
var perms = [];
perms.push(item);
var isItemPush = false;
var counter = 0
var innerSubset = function () {
if (item + items[counter] === target) {
perms.push(items[counter])
items.splice(counter, 1);
results.push(perms);
isItemPush = true;
} else {
if (counter < items.length) {
counter += 1;
innerSubset();
}
}
}
innerSubset();
} else {
results.push(item);
}
if (items.length === 0) {
return results;
}
return ss(items);
}
return ss(items)
}
window.onload = function () {
var items = [4, 6, 8, 12, 4, 6, 6, 12, 4, 4];
target = 12;
result = subset_sum(items, target);
console.log(result);
}
The problem with this approach is that it is only one or two dimensional. From the example above, it does not return the result [4,4,4] and 6.
Very similar solution to yours, a bit unclear if it's helpful:
numbers = [4, 6, 8, 12, 4, 6, 6, 12, 4, 4];
var result = createSubsets(numbers, 12);
console.log('Result', JSON.stringify(result));
function createSubsets(numbers, target) {
// filter out all items larger than target
numbers = numbers.filter(function (value) {
return value <= target;
});
// sort from largest to smallest
numbers.sort(function (a, b) {
return b - a;
});
// array with all the subsets
var result = [];
while (numbers.length > 0) {
var i;
var sum = 0;
var addedIndices = [];
// go from the largest to the smallest number and
// add as many of them as long as the sum isn't above target
for (i = 0; i < numbers.length; i++) {
if (sum + numbers[i] <= target) {
sum += numbers[i];
addedIndices.push(i);
}
}
// remove the items we summed up from the numbers array, and store the items to result
// since we're going to splice the numbers array several times we start with the largest index
// and go to the smallest to not affect index position with splice.
var subset = [];
for (i = addedIndices.length - 1; i >= 0; i--) {
subset.unshift(numbers[addedIndices[i]]);
numbers.splice(addedIndices[i], 1);
}
result.push(subset);
}
return result;
}
Produces array:
[12],[12],[8,4],[6,6],[6,4],[4,4]
There's no limit regarding the subset length. If you add one more 4 to the numbers array you will get result:
[12],[12],[8,4],[6,6],[6,4],[4,4,4]
JSFiddle: http://jsfiddle.net/kUELD/

Categories