latest elements in array not found? codewars kata - javascript

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.

Related

Find the smallest missing positive int in array in js

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

JS Number of occurences in a sequence is a prime number

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)

Add every n items in an array

I have an array like so:
[5, 12, 43, 65, 34 ...]
Just a normal array of numbers.
What I wan't to do is write a function group(n, arr) which adds every n numbers in the array.
For example if I call group(2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) it should return
[
3 //1+2,
7 //3+4,
11 //5+6,
15 //7+8,
19 //9+10,
11 //whatever remains
]
I haven't tried anything yet, I will soon update with what I can.
You can use .reduce as follows:
function group(n, arr) {
// initialize array to be returned
let res = [];
// validate n
if(n > 0 && n <= arr.length) {
// iterate over arr while updating acc
res = arr.reduce((acc, num, index) => {
// if the current index has no remainder with n, add a new number
if(index%n === 0) acc.push(num);
// else update the last added number to the array
else acc[acc.length-1] += num;
// return acc in each iteration
return acc;
}, []);
}
return res;
}
console.log( group(2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) );
This approach features two loops, one for checking the outer index and anoter for iterating the wanted count of items for summing.
function group(n, array) {
const result = [];
let i = 0;
while (i < array.length) {
let sum = 0;
for (let j = 0; j < n && i + j < array.length; j++) {
sum += array[i + j];
}
result.push(sum);
i += n;
}
return result;
}
console.log(group(2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]));
You could use Array.from to create the result array and then use its mapper to make the sums. These sums can be made by using reduce on the relevant slice of the array .
This is a functional programming solution:
const group = (step, arr) =>
Array.from({length: Math.ceil(arr.length/step)}, (_, i) =>
arr.slice(i*step, (i+1)*step).reduce((a, b) => a+b)
);
console.log(group(2, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]));

Find all the same numbers in the array

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

Sorting an increasing number in an array in Javascript

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)

Categories

Resources