How do I find the smallest missing positive integer from an array of integers in js? I didn't find an answer to my question, all I found was in other languages.
Here's an example array:
[-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2]
The result should be 8.
You could take an object of seen values and a min variable for keeping track of the next minimum value.
const
data = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2],
ref = {};
let min = 1;
for (const value of data) {
if (value < min) continue;
ref[value] = true;
while (ref[min]) min++;
}
console.log(min);
You could create an array of positive integer (in this example integers has values from 0 to 10), then use Math.min on integers array filtered with initial array (that was filtered taking only positive numbers):
let integers = Array.from(Array(11).keys());
let arr = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2];
console.log(Math.min(...integers.filter(x => x > 0 && !arr.filter(x => x > 0).includes(x))));
You can do like below to avoid multiple loops.
Simplest solution is when numbers from 1-10, sum of all number will 55 using this formula (n * (n + 1)) / 2;.
the missing number will be 55-(sum of remaining numbers).
const list = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2];
const missing = (list) => {
let sum = 0;
let max = 0;
let ref = {};
for (let i = 0; i < list.length; i++) {
const ele = list[i];
if (ele > 0 && !ref[ele]) {
ref[ele] = true;
max = max < ele ? ele : max;
sum += ele;
}
}
const total = (max * (max + 1)) / 2;
return total - sum; // will work if only one missing number
// if multiple missing numbers and find smallest one
// let result = 0;
// for (let i = 1; i <= total - sum; i++) {
// if (!ref[i]) {
// result = i;
// break;
// }
// }
// return result;
};
console.log(missing(list));
I create function for finding the smallest positive.
arr = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2]
function getSmallestPos(arr) {
pi = [...new Set(
arr.filter(n => n > 0)
.sort((a, b) => a - b ))
];
for (i = 0; i < pi.length; i++) {
if ( pi[i] != (i+1)) {
return (i+1);
}
}
}
console.log(getSmallestPos(arr));
Your questions title contradicts the body of your answer.
To get the smallest positive integer you might try this:
const array = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2];
// filter array to get just positive values and return the minimum value
const min = Math.min(...array.filter(a => Math.sign(a) !== -1));
console.log(min);
For getting the missing value check this out:
const array = [-2, 6, 4, 5, 7, -1, 1, 3, 6, -2, 9, 10, 2, 2];
const getMissingPositiveInt = (array) => {
// filter array to get just positive values and sort from min to max (0, 1, 4, 5 ...)
const min = array.filter(a => Math.sign(a) !== -1).sort((a,b) => a-b);
for (let i=min[0]; i<array.length; i++) // loop from min over whole array
if (!min.includes(i)) // if array doesnt include index ...
return i; // ... you got your missing value and can return it
}
console.log(getMissingPositiveInt(array));
Related
I'm solving the following kata:
Given an input of an array of digits, return the array with each digit incremented by its position in the array: the first digit will be incremented by 1, the second digit by 2, etc. Make sure to start counting your positions from 1 (and not 0).
Your result can only contain single digit numbers, so if adding a digit with it's position gives you a multiple-digit number, only the last digit of the number should be returned.
Notes:
return an empty array if your array is empty
arrays will only contain numbers so don't worry about checking that
Examples
[1, 2, 3] --> [2, 4, 6] # [1+1, 2+2, 3+3]
[4, 6, 9, 1, 3] --> [5, 8, 2, 5, 8] # [4+1, 6+2, 9+3, 1+4, 3+5]
# 9+3 = 12 --> 2
My code:
const incrementer = (arr) => {
if (arr === []) {
return []
}
let newArr = []
for (let i = 0; i <= arr.length; i++) {
let result = arr[i] + (i + 1)
newArr.push(result)
if (newArr[i] > 9 ) {
let singleDigit = Number(newArr[i].toString().split('')[1])
newArr.push(singleDigit)
}
}
const filteredArr = newArr.filter(el => el >= 0 && el <= 9)
return filteredArr
}
I can't seem to pass the latest test case, which is the following:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 8]), [2, 4, 6, 8, 0, 2, 4, 6, 8, 9, 0, 1, 2, 2]
I keep getting back the whole correct array up until the second 0, after which the other numbers, 1,2,2 are missing from the solution. What am I doing wrong?
The problem in your code is that the filter only runs at the end, and so when you have done a double push in one iteration (once with the value that has more than one digit, and once with just the last digit), the next iteration will no longer have a correct index for the next value that is being pushed: newArr[i] will not be that value.
It is better to correct the value to one digit before pushing it to your new array.
Moreover, you can make better use of the power of JavaScript:
It has a nice map method for arrays, which is ideal for this purpose
Use modulo arithmetic to get the last digit without having to create a string first
Here is the proposed function:
const incrementer = (arr) => arr.map((val, i) => (val + i + 1) % 10);
console.log(incrementer([1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 8]));
... so if adding a digit with it's position gives you a multiple-digit number, only the last digit of the number should be returned.
So if the number is 12, it expects only 2 to be added to the array.
So your code should be:
if (newArr[i] > 9)
{
newArr[i] = newArr[i] % 10; // remainder of newArr[i] / 10
}
const incrementer = (arr) => {
if (arr.length === 0) { // CHANGE HERE
return [];
}
let newArr = []
for (let i = 0; i <= arr.length; i++) {
let result = arr[i] + (i + 1)
newArr.push(result)
if (newArr[i] > 9 ) {
newArr[i] = newArr[i] % 10; // CHANGE HERE
}
}
const filteredArr = newArr.filter(el => el >= 0 && el <= 9)
return filteredArr
}
console.log(incrementer([2, 4, 6, 8, 0, 2, 4, 6, 8, 9, 0, 1, 2, 2]));
console.log(incrementer([1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 8]));
Please see below code.
const incrementer = arr => {
if (arr === []) {
return [];
}
let newArr = [];
for (let i = 0; i < arr.length; i++) {
let result = arr[i] + (i + 1);
// newArr.push(result);
if (result > 9) {
let singleDigit = Number(result.toString().split("")[1]);
newArr.push(singleDigit);
} else {
newArr.push(result);
}
}
// const filteredArr = newArr.filter(el => el >= 0 && el <= 9);
return newArr;
};
console.log(incrementer([1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 9, 9, 9, 8]))
const incrementer = (arr) => {
if (arr === []) {
return []
}
return arr.map((number, index) => (number + index + 1) % 10);
}
Doing the needed additions in (number + index + 1) and % 10 operation will get the last digit.
I have two arrays (X and Y) and I need to create array Z that contains all elements from array X except those, that are present in array Y p times where p is a prime number.
I am trying to write this in JS.
For Example:
Array X:
[2, 3, 9, 2, 5, 1, 3, 7, 10]
Array Y:
[2, 1, 3, 4, 3, 10, 6, 6, 1, 7, 10, 10, 10]
Array Z:
[2, 9, 2, 5, 7, 10]
So far I have this:
const arrX = [2, 3, 9, 2, 5, 1, 3, 7, 10]
const arrY = [2, 1, 3, 4, 3, 10, 6, 6, 1, 7, 10, 10, 10]
const arrZ = []
const counts = [];
// count number occurrences in arrY
for (const num of arrY) {
counts[num] = counts[num] ? counts[num] + 1 : 1;
}
// check if number is prime
const checkPrime = num => {
for (let i = 2; i < num; i++) if (num % i === 0) return false
return true
}
console.log(counts[10]);
// returns 4
Any hint or help appreciated. Thanks!
You're on the right track. counts should be an object mapping elements in arrY to their number of occurrences. It's easily gotten with reduce.
The prime check needs a minor edit, and the last step is to filter arrX. The filter predicate is just a prime check on the count for that element.
// produce an object who's keys are elements in the array
// and whose values are the number of times each value appears
const count = arr => {
return arr.reduce((acc, n) => {
acc[n] = acc[n] ? acc[n]+1 : 1;
return acc;
}, {})
}
// OP prime check is fine, but should handle the 0,1 and negative cases:
const checkPrime = num => {
for (let i = 2; i < num; i++) if (num % i === 0) return false
return num > 1;
}
// Now just filter with the tools you built...
const arrX = [2, 3, 9, 2, 5, 1, 3, 7, 10]
const arrY = [2, 1, 3, 4, 3, 10, 6, 6, 1, 7, 10, 10, 10]
const counts = count(arrY);
const arrZ = arrX.filter(n => checkPrime(counts[n]));
console.log(arrZ)
I have an array with numbers in the range of 0 - 100. I need to find all the same numbers and add 1 to them.
my code worked well with arrays like [100, 2, 1, 1, 0]
const findAndChangeDuplicates = (arr: any) => {
for (let i = arr.length - 1; i >= 0; i--) {
if (arr[i + 1] === arr[i] && arr[i] <= 5) {
arr[i] += 1;
} else if (arr[i - 1] === arr[i] && arr[i] >= 5) {
arr[i] -= 1;
findAndChangeDuplicates(arr);
}
}
return arr;
};
but when I came across this
[100, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0]
my code let me down.
Expected Result:
[100, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Have any ideas?
An approach by using at least one loop from the end to adjust the values and if necessary another loop from the beginning to set the largest value to 100.
Both loops feature a value variable v. In the first loop, it starts with the last value of the array and increments its value and check is the item is smaller than this value.
If smaller, then the value is assigned, otherwise the actual value is taken for the next item.
if necessary, the other loop works in opposite direction and with a start value of 100 and checks if the item is greater than wanted and takes the smaller value, or the value is taken from the item.
The result is an array which has a gereatest value of 100 at start and goes until zero or greater to the end of the array.
function update(array) {
var i = array.length,
v = array[--i];
while (i--) if (array[i] < ++v) array[i] = v; else v = array[i];
if (array[0] > 100) {
v = 100;
for (i = 0; i < array.length; i++) {
if (array[i] > v) array[i] = v; else v = array[i];
v--;
}
}
return array;
}
console.log(update([100, 2, 1, 1, 0]));
console.log(update( [100, 100, 99, 86, 6, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0]))
.as-console-wrapper { max-height: 100% !important; top: 0; }
The following assumes you want them ordered from highest to lowest, if not this might ba as well as useless to you.
The idea is to first create an Object to keep track of how many of each number exist. We then map each value by first checking whether it's unique and if not increasing it until we can't find any value inside the Object anymore. This will not neatly order the numbers by itself so we will have to sort afterwards.
let arr1 = [100, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0],
arr2 = [100, 2, 1, 1, 0];
const f = (arr) => arr.reduce((a,c) => (a[c] = (a[c] || 0) + 1, a),{}),
g = (arr, obj) => arr.map(v => {
if (obj[v] > 1) {
let i = 1;
obj[v] = obj[v] - 1;
while (obj[v + i]) {
i++;
}
obj[v + i] = (obj[v + i] || 0) + 1;
return v + i;
} else {
return v;
}
}).sort((a,b) => +b - +a);
console.log(g(arr1, f(arr1)))
console.log(g(arr2, f(arr2)))
Here is a verbose solution that will work with unordered arrays as well.
It's not efficient, neither brilliant, but it takes care of unordered arrays as well.
Basically, it takes advantage of reduce to collect all the occurrences of each element. Each time it finds more than one, it increases all the occurrences by 1 except the last one.
Next, it checks whether there still are duplicates. If there are, it repeats the process until none is found. Of course, it's not the cleverest approach, but it works.
// Increases all duplicates until there are no more duplicates.
const increaseDuplicates = (arr, index) => {
// Repeat the code until no duplicate is found
while (!noDuplicates(arr)) {
// Acquire all the occurrences of each item, keeping track of the index.
Object.entries(arr.reduce((acc, next, i) => {
acc[next] = acc[next] || [];
return acc[next].push(i), acc;
}, {})).forEach(([n, indexes]) => {
// for each value found, check whether it appears at least twice.
if (indexes.length > 1) {
// if it does, increase the value of every item but the last one.
for (var i = 0; i < indexes.length - 1; i++) {
arr[indexes[i]]++;
}
}
});
}
return arr;
};
// Asserts an array has no duplicates.
const noDuplicates = (arr) => [...new Set(arr)].length === arr.length;
const input = [100, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0];
console.log(increaseDuplicates(input));
const unorderedInput = [6,4,5,6,6,6,6,5,6,3,1,2,3,99,403,100, 6, 6, 6, 5, 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 2, 2, 2, 1, 1, 0, 0];
console.log(increaseDuplicates(unorderedInput));
You can use a forEach on your array to do this, using the 3rd parameter of the callback, the array itself, and a bit of recursivity
const increment_to_unicity = (value, index, self) => {
if (self.indexOf(value) !== index) {
self[index]++
increment_to_unicity(self[index], index, self)
}
return self[index];
}
arr = arr.map(increment_to_unicity).sort((a, b) => b - a);
I'm running into a error in stopping the execution when a lower number occurs in the data of an array
Let seat1 = [2, 5, 6, 9, 2, 12, 18];
console should log the values till it gets to 9 since
2 < 5 < 6 < 9
then omit 2 since 9 > 2
then continue from 12 < 18.
let num = [2, 5, 6, 9, 2, 12, 18];
for (let i = 0; i < num.length; i++) {
if ((num[i] + 1) > num[i]) {
console.log(num[i])
} else {
console.log('kindly fix')
}
}
Use Array.reduce() to create a new array without the items that are not larger than the last item in the accumulator (acc) or -Infinity if it's the 1st item:
const num = [2, 5, 6, 9, 2, 3, 12, 18];
const result = num.reduce((acc, n) => {
if(n > (acc[acc.length - 1] || -Infinity)) acc.push(n);
return acc;
}, []);
console.log(result);
simple answer using if and for -
let num = [2, 5, 6, 9, 2 , 3, 12, 16, 9, 18];
let max = 0;
for (let i = 0; i < num.length; i++)
{
if ((i == 0) || (num[i] > max)) {
max = num[i];
console.log (num[i]);
}
}
You could filter the array by storing the last value who is greater than the last value.
var array = [2, 5, 6, 9, 2, 3, 12, 18],
result = array.filter((a => b => a < b && (a = b, true))(-Infinity));
console.log(result)
Store the max value and check num[i] against the current max. If num[i] is bigger, log it and set the new max value. Initial max value should be first num value but smaller so it doesn't fail on the first check.
let num = [2, 5, 6, 9, 2, 12, 18];
let max = num[0] - 1;
for (let i = 0; i < num.length; i++) {
if (num[i] > max) {
console.log(num[i]);
max = num[i];
}
}
let num = [2, 5, 6, 9, 2, 12, 18];
let result = num.sort((a, b) => a - b).filter((elem, pos, arr) => {
return arr.indexOf(elem) == pos;
})
console.log(result)
It is for a studying purpose. Have a big array of integers need to return an array that has 1 added to the value represented by the array.
Tried to convert the array into an integer, but after using
parseInt('9223372036854775807', 10) received 9223372036854776000, instead of 9223372036854775807
What is going wrong here?
var arr = [ 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 7 ];
function upArray(arr){
var numb = arr.join('');
numb = parseInt(numb, 10);
var result = numb + 1;
console.log(result);
result = result.toString(10).split('').map(Number);
return result;
}
You are exceeding the capacity of JavaScript's number type
IEEE-754 double-precision floating point (the kind of number JavaScript uses) can't precisely represent all numbers
Beyond Number.MAX_SAFE_INTEGER + 1 (9007199254740992), the IEEE-754 floating-point format can no longer represent every consecutive integer
also you dont need to use a second argument to parseInt unless you are looking to use a different base than decimal
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
If you use the code with an array of numbers that when joined is within this limit your code will work
var arr = [ 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5 ];
function upArray(arr){
var numb = arr.join('');
numb = parseInt(numb);
var result = numb + 1;
console.log(result)
result = result.toString(10).split('').map(Number);
return result;
}
console.log(upArray(arr))
As you're exceeding the MAX_SAFE_INTEGER.
If you just want to display you can go this way
var arr = [ 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 7 ];
function addone(arr){
let carry = 0;
for(let i=arr.length-1; i>=0; i--){
if(i === arr.length-1) {
if( arr[i]+1 > 9){
arr[i] = 10-(arr[i] + 1);
carry = 1;
} else {
arr[i] +=1;
carry= 0;
}
}
if( i !== arr.length-1 ){
if( carry === 0) break;
if( arr[i]+1+carry > 9){
arr[i] = 10-(arr[i] + carry);
carry = 1;
} else {
arr[i] +=carry;
carry= 0;
}
}
}
if(carry === 1)
arr.unshift(1)
return arr;
}
console.log(addone(arr).join(''))
console.log(addone([1,2,9]).join(''))
console.log(addone([9,9,9]).join(''))
The value is going beyond the max number value.
Here is recursive appproch for the problem:
function upArray(arr, lastIndex){
if(lastIndex == undefined){
lastIndex = arr.length - 1;
}
if(lastIndex < 0){
return;
}
if(arr[lastIndex] == 9){
arr[lastIndex] = 0;
upArray(arr, lastIndex - 1);
}
else {
arr[lastIndex] = arr[lastIndex] + 1;
}
return arr;
}
var arr = [ 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 9];
var result = upArray(arr);
console.log(result);
Another solution so you can choice =)
var arr = [9,9,9];//[ 9, 2, 2, 3, 3, 7, 2, 0, 3, 6, 8, 5, 4, 7, 7, 5, 8, 0, 7 ];
var i = arr.length;
var append = true;
while(append){
if(--i < 0){
arr.unshift(1);
break;
}
var v = arr[i];
if(++v >= 10)
v -= 10;
else
append = false;
arr[i] = v;
}
var r = arr.join('');
console.log(r);
it means the maximum range for an Intiger number has reached, here is a link
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER
to solve this split the array value and add one to it and then combine then back and display the entire array as a String (don't parse it).
function upArray(arr){
var temp = arr;
var len = arr.length;
var temp2 = arr;
temp2 = temp2.slice(0,len/2).join('');
temp2 = parseInt(temp2);
temp = temp.slice(len/2).join('');
numb = parseInt(temp) +1;
if(numb.toString().length > (len/2 + len%2))
{
numb = numb.toString().slice(1);
temp2++;
}
var result = temp2.toString() + numb.toString();
console.log(result);
result = result.split('').map(Number);
return result;
}
hope it helps and have pass through every test...
As everybody would agree that the issue here is having a value that is exceeding the capacity of JavaScript's number type, we can expect that there'll be proposed workarounds like having to split the array into multiple array and work from there.
We can actually solve this on another approach. Since your representation of a number is splitting it into single digits stored as an array, and you want to perform a simple addition on it, we can observe a representation of a simple/elementary addition. The one where we add a value digit by digit from the bottom and make use of the "Carry Over" concept. We can actually do it that way.
It will look somewhat like this (A bit longer code for readability):
var x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9];
var y = [9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9];
var add1 = (arr) => {
var hasCarryOver = true;
for (var index = arr.length - 1; index >= 0; index--) {
if (!hasCarryOver) {
break;
}
if (arr[index] < 9) {
arr[index] = arr[index] + 1;
hasCarryOver = false;
} else {
arr[index] = 0;
}
}
if (hasCarryOver) {
arr.unshift(1);
}
return arr;
};
x = add1(x);
y = add1(y);
console.log('result x add 1', x);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 9, 0]
console.log('result y add 1', y);
// [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]