Codewars Challenge - Count of positives / sum of negatives - javascript

My code works but it's not being accepted in order to pass the challenge. Any help on what I'm doing wrong would be appreciated.
Challenge Description:
Given an array of integers.
Return an array, where the first element is the count of positives numbers and the second element is sum of negative numbers.
If the input array is empty or null, return an empty array:
C#/Java: new int[] {} / new int[0];
C++: std::vector<int>();
JavaScript/CoffeeScript/PHP/Haskell: [];
Rust: Vec::<i32>::new();
ATTENTION!
The passed array should NOT be changed. Read more here.*
For example:
input [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15]
return [10, -65].
My Code:
function countPositivesSumNegatives(input) {
if (input.length < 1){
return [];
}
var newArray = [0, 0];
for (var i = 0; i < input.length; i++){
if (input[i] > 0)
{
newArray[0] += 1;
}
else {
newArray[1] += input[i];
}
}
return newArray;
}

You're not checking for null when the challenge explicitly requires that "if the input array is empty or null, return an empty array". Please consider changing the code as follows
if (input == null || input.length < 1){
return [];
}

This code is working for me (in JavaScript)
function countPositivesSumNegatives(input) {
if (input === null || input.length < 1) {
return [];
}
var array = [0, 0];
for(var i = 0; i < input.length; i++) {
if(input[i] <= 0) {
array[1] += input[i];
} else {
array[0] += 1;
}
}
return array;
}
So, you need check if input === null (and return empty array), and if input[i] <= 0 (to sum of negatives)

Here is an approach I used in Javascript so maybe you can borrow afew ideas off it as well
function countPositivesSumNegatives(input) {
if (input == null || input.length < 1){
return [];
}
var sum =0;
var pos =[];
for (var i=0; i<input.length; i++){
if(input[i]>0){
pos.push(input[i]);
} else{
sum += input[i];
}
}
return [pos.length, sum];
}

Here is my solution for this task:
function countPositivesSumNegatives(input) {
let sumOfPositive = 0;
let sumOfNegative = 0;
if(input == null || input.length < 1) {
return [];
} else {
input.map(item => {
if(item > 0) {
sumOfPositive++;
} else if(item < 0) {
sumOfNegative += item;
} else {
return []
}
})
}
return [sumOfPositive, sumOfNegative]
}

Here is my solution for this task:
function countPositivesSumNegatives (a) {
if (!a || !a.length) return []
let pos = a.filter(x => x > 0),
neg = a.filter(x => x <= 0)
return [pos.length, Math.floor(neg.reduce((s,v)=>s+v,0))]
}
solution for codewars

Meet the longest code in the topic
function countPositivesSumNegatives(input) {
if (input && input.length > 1) {
let count = [];
let sum = [];
for (i=0; i<input.length; i++) {
if (input[i] > 0) {
count.push(input[i]);
} if (input[i] < 0) {
sum.push(input[i]);
}
};
let sumNegatives = 0
for (i=0; i<sum.length; i++) {
sumNegatives += sum[i];
}
let result = [count.length, sumNegatives];
return result;
};
if (input === null || input.length < 1) {
let result = [];
return result;
};
if (input[0] < 0) {
let result = [0, input[0]]
return result
}
}

function countPositivesSumNegatives(input) {
const pos = input.filter((el) => el >= 1).length;
const neg = input.filter((el) => el < 0);
const negSums = neg.reduce((a, b) => a + b, 0);
(input === null || input.length == 0) ? [] : (input.forEach((num) => num > 0 ? pos : []))
const finalArr = [];
finalArr.push(negSums);
finalArr.unshift(pos);
return finalArr;
}

This one definitely works ::
function countPositivesSumNegatives(input) {
let positiveNums = 0;
// initialize positive number variable
let negativeNums = 0;
// initialize negative number variable
if (input === null || input.length === 0) {
return []; // if the input is empty or null, it will return empty array
} else {
input.forEach((num) => num > 0 ? positiveNums++ : negativeNums += num);
}
return [positiveNums , negativeNums];}
For positive numbers, it will add the current number to the previous number and return the latest available value after iterating through the whole array.

Related

To get empty array

I wrote a code but i met a some strange thing.
function countPositivesSumNegatives(input) {
let count = 0;
let positive = 0;
let negative = 0;
for (let i = 0; i < input.length; i++) {
if (input[i] < 0) {
negative += input[i];
}
if (input[i] > 0) {
count++;
positive = count;
}
if (input == 0) {
return [];
}
}
return [positive, negative];
}
console.log(countPositivesSumNegatives([0, 0]));
Why output is [0, 0] instead of [] ?
I'm trying to get just empty array []
Output has to be:
countPositivesSumNegatives([1, 2, 3, -1, -3]) -> [3, -4]
countPositivesSumNegatives([0, 0]) -> []
(UPDATED)
Since the function should return [] only if all elements are == 0, you can check at the end of the loop if positive and negative are == 0, meaning no positive numbers have been counted and no negative numbers have been summed:
function countPositivesSumNegatives(input) {
let count = 0;
let positive = 0;
let negative = 0;
for (let i = 0; i < input.length; i++) {
if (input[i] < 0) {
negative += input[i];
}
if (input[i] > 0) {
count++;
positive = count;
}
}
if (positive === 0 && negative === 0) {
return [];
}
else {
return [positive, negative];
}
}
console.log(countPositivesSumNegatives([0, 0]));
The only time you return [] is when the condition (input[i] == 0) matches on any element.
However, given the name of the function you only want to skip such elements.
If and only if the argument contains no other elements but 0, return the empty array.
So the following modified code will work:
function countPositivesSumNegatives(input) {
let count = 0;
let positive = 0;
let negative = 0;
for (let i = 0; i < input.length; i++) {
if (input[i] < 0) {
negative += input[i];
}
if (input[i] > 0) {
count++;
}
}
positive = count; // Hoisted out of the loop. Unless your function contains more code, you do not need the 'count' variable at all.
let seen_nonzero = ((positive !== 0) || (negative !== 0));
// Flags whether a non-0 element is present in your input.
let a_r =
seen_nonzero
? [positive, negative]
: []
;
return a_r
}
console.log(countPositivesSumNegatives([0, 0]));
console.log(countPositivesSumNegatives([1, 2, 3, -1, -3]));
console.log(countPositivesSumNegatives([-1, -2, 0, 1, 2]));

Permutation: Push function not working, JavaScript O(n*n!) runtime

The problem at hand is :
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
I have this code with an ok run time but it seems that the push function is not working, I am not sure why bc it all makes sense in general
Example 1:
Input: nums = [1,2,3]
Output: [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
Constraints:
1 <= nums.length <= 6
-10 <= nums[i] <= 10
All the integers of nums are unique.
var permute = function(nums) {
if (nums == null) {
return []
}
return getPermutations(nums);
};
function getPermutations(arr) {
var set = {}
var size = factorial(arr.length)
var result = []
while (Object.keys(set).length < size) {
for (var i = 0; i < arr.length && result.length < size; i++) {
for (var j = arr.length - 1; j >= 0 && result.length < size; j--) {
if (!set[arr]) {
set[arr] = 1
console.log(arr) //clearly see the permutations printed
result.push(arr) //why is this not working...
}
arr = swap(arr,i,j)
}
}
}
return result
}
function swap(arr,i,j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
return arr
}
function factorial(n) {
if (n == 0 || n == 1) {
return 1
}
return n*factorial(n-1)
}
You're pushing the same array multiple times into the result array.
You can fix this by creating a copy of the arr array before pushing it.
(So the code after it can't mutate the array again)
So instead of result.push(arr) you could use one of those examples:
// using splash operator
result.push([...arr]);
// Array#slice()
result.push(arr.slice());
// Array.from()
result.push(Array.from(arr));
// etc...
Working Example:
var permute = function(nums) {
if (nums == null) {
return []
}
return getPermutations(nums);
};
function getPermutations(arr) {
var set = {}
var size = factorial(arr.length)
var result = []
while (Object.keys(set).length < size) {
for (var i = 0; i < arr.length && result.length < size; i++) {
for (var j = arr.length - 1; j >= 0 && result.length < size; j--) {
if (!set[arr]) {
set[arr] = 1
console.log(arr) //clearly see the permutations printed
result.push([...arr]) //why is this not working...
}
arr = swap(arr,i,j)
}
}
}
return result
}
function swap(arr,i,j) {
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
return arr
}
function factorial(n) {
if (n == 0 || n == 1) {
return 1
}
return n*factorial(n-1)
}
console.log(permute([1,2,3]));
This question could also be a good read, it contains a lot of examples for how to efficiently calculate permutations in javascript.

JavaScript find longest Uniform Substring

Trying to find longest Uniform Substring.
Suppose I have abbbccda then it should return [1, 3]. Because it starts from index 1 and is 3 characters long.
Other Example:
"10000111" => [ 1, 4 ]
"aabbbbbCdAA" => [ 2, 5 ]
I tried:
function longestUniformSubstring(input){
if(input){
let arr = input.split("");
let obj = {};
arr.map((ele, index) => {
return obj[ele] ? obj[ele][1]++ : obj[ele] = [index,1];
});
console.log(obj);
return obj;
}
else {
return [ -1, 0 ];
}
}
longestUniformSubstring("abbbccda");
It gives me object of all character But, no idea how can i get with highest length.
You could iterate the string and check the previous character and continue if the caracters are equal.
If not, check the length and assign a new logest array, if necessary and check if a longer string is not possible, then break the loop.
Assign the new found character and set a new start value to the actual index.
function longestUniformSubstring(input) {
var longest = [-1, 0],
start = 0,
character = input[0];
for (let i = 1; i <= input.length; i++) {
if (input[i] === character) continue;
if (longest[1] < i - start) {
longest = [start, i - start];
if (i + i - start >= input.length) break;
}
character = input[i];
start = i;
}
return longest;
}
console.log(...longestUniformSubstring("aabbbbbCdAA"));
console.log(...longestUniformSubstring("ab"));
console.log(...longestUniformSubstring("aa"));
console.log(...longestUniformSubstring(""));
You can keep track of the character being evaluated. When it changes, check to see if its repetition is larger than previous repetitions. If so, store the new version and move on.
function longestUniformSubstring(input){
const result = [-1, 0];
let currentCharacter = '';
let currentIndex = -1;
let currentCount = 0;
(input || '').split('').forEach((character, index) => {
if (character == currentCharacter) {
currentCount++;
} else {
if (currentCount > result[1]) {
result[0] = currentIndex;
result[1] = currentCount;
}
currentCharacter = character;
currentIndex = index;
currentCount = 1;
}
});
if (currentCount > result[1]) {
result[0] = currentIndex;
result[1] = currentCount;
}
return result;
}
console.log(longestUniformSubstring("abbbccdddda"));
You can write the logic like this, this works at my end.
function longestUniformSubstring(input) {
let length = input.length;
let firstLetter = input[0];
let sIndex = 0;
let eIndex = 0;
let resultIndex = 0;
let resultLength = 0;
while(sIndex < length && eIndex < length) {
if (input[eIndex] === firstLetter) {
eIndex++;
if (eIndex - sIndex > resultLength) {
resultLength = eIndex - sIndex;
resultIndex = sIndex;
}
}
else {
sIndex++;
if (input[sIndex] !== firstLetter)
{
firstLetter = input[sIndex];
}
}
}
return [resultIndex, resultLength];
}
console.log(longestUniformSubstring('AABBBBBCC'));
You can create a queue, to keep track of elements. and pop once all the iteration has been done.
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
let queue = [];
const map = {};
for (let index = 0; index < input.length; index++) {
const char = input[index];
if (!map[char]) map[char] = [index, 1];
else {
map[char][1] += 1;
}
const max = queue[0];
if (max && max[1] < map[char][1]) {
queue.unshift(map[char]);
} else {
queue.push(map[char]);
}
}
return queue.shift();
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
The dirty one, keep track of longest
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
let max = ["", -1, 0];
let map = {}
for (let index = 0; index < input.length; index++) {
const char = input[index];
if (!map[char]) map[char] = [index, 1];
else {
map[char][1] += 1;
}
if (max[2] < map[char][1]) {
max = [char, map[char][0], map[char][1]];
}
}
return [max[1], max[2]];
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
You can use .reduce to count. .sort method to get the min or max.
function longestUniformSubstring(input) {
if (!input) return [-1, 0];
const map = input.split("").reduce((m, item, index) => {
if (!m[item]) m[item] = [index, 1];
else {
m[item][1] += 1;
}
return m;
}, {});
return Object.values(map).sort(([_, i], [__, j]) => j - i)[0];
}
console.log(longestUniformSubstring("abbbccda"));
console.log(longestUniformSubstring("10000111"));
console.log(longestUniformSubstring("aabbbbbCdAA"));
You can just iterate over
function longestUniformSubstring(input){
if(!input) {
return [-1, 0];
}
let lastIndex=0;
let lastLength=1;
let currIndex=0;
let currLength=0;
for (let i = 1; i < input.length; i++) {
if(input.charAt(i)===input.charAt(i-1)) {
currLength++;
} else {
if (currLength > lastLength) {
lastIndex = currIndex;
lastLength = currLength;
}
currIndex = i;
currLength = 1;
}
}
return [lastIndex, lastLength];
}

Finding all divisors of integer besides the int itself and 1, and putting result into array

So I've gotten the function to return the divisors beside 1 and itself, but my loop is still adding empty array elements since it increments the int argument. Can someone see where I'm going wrong?
function divisors(integer) {
var result = [];
for(let i = 0; i < integer; i++) {
if(i !== 1 && i !== integer && integer % i == 0) {
result[i] = i;
}
}
return result;
};
console.log(divisors(12)); // returns array length of 7, 3 emtpy slot and 2, 3, 4, 6 ??
You should add the elements using push()
function divisors(integer) {
var result = [];
for(let i = 0; i < integer; i++) {
if(i !== 1 && i !== integer && integer % i == 0) {
result.push(i)
}
}
return result;
};
console.log(divisors(12));
A better way is to start the loop from 2. And no need to check i !== integer because i will be always less than integer.
function divisors(integer) {
var result = [];
for(let i = 2; i < integer; i++) {
if(integer % i == 0) {
result.push(i)
}
}
return result;
};
console.log(divisors(12));
A more cleaner on-liner will be using filter()
const divisors = num => [...Array(num)]
.map((x,i) => i)
.filter(x => num % x === 0).slice(1)
console.log(divisors(12));

Return 0 if there are no string in an array - JS

I have a function here that takes the smallest number in an array.
What I did is that I filtered out only numbers using typeof property and compared the values from Infinity.
Right now, it will return 0 if the array is empty.
However if the array contains only string or other datatypes it will return Infinity.
Here's my codes:
function findSmallestNumberAmongMixedElements(arr) {
var smallestNum = Infinity;
if(arr.length !== 0){
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] === 'number' && arr[i] < smallestNum){
smallestNum = arr[i];
}
}
return smallestNum;
}
return 0;
}
var output = findSmallestNumberAmongMixedElements(['sam', 3, 2, 1]);
console.log(output); // --> 4
It must return 0 as well if there are no numbers in the array.
Any idea what am I doing wrong here?
There are probably some more elegant ways to solve this. but this fixes your bug.
function findSmallestNumberAmongMixedElements(arr) {
var smallestNum = Infinity;
var numberFound = false
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] === 'number' && arr[i] < smallestNum){
smallestNum = arr[i];
numberFound = true
}
}
if(numberFound)
return smallestNum;
return 0;
}
The problem is that you are special-casing the empty-array case, with the line
if(arr.length !== 0){
Remove that. Then, if you want to force a result of Infinity to 0, do that at the end.
function findSmallestNumberAmongMixedElements(arr) {
var smallestNum = Infinity;
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] === 'number' && arr[i] < smallestNum){
smallestNum = arr[i];
}
}
return isFinite(smallestNum) ? smallestNum : 0;
}
However, it is simpler to just filter out the non-numbers using filter, and calculate the minimum using Math.min. This also makes easier to fix a "bug" in the code above, which is that it will yield 0 for inputs such as [Infinity, "foo", Infinity]. I'm not sure whether you prefer to return 0 or Infinity in that kind of case. Assuming you do want to return 0, then
function findSmallestNumberAmongMixedElements(arr) {
var nums = ...arr.filter(elt => typeof elt === 'number');
return nums.length ? Math.min(...nums) : 0;
}
function findSmallestNumberAmongMixedElements(arr) {
var smallestNum = Infinity;
if(arr.length !== 0){
for(var i = 0; i < arr.length; i++){
if(typeof arr[i] === 'number' && arr[i] < smallestNum){
smallestNum = arr[i];
}
}
return smallestNum == Infinity? 0 : smallestNum; // if smallest doesn't change return 0
}
return 0;
}
var output = findSmallestNumberAmongMixedElements(['sam', 3, 2, 1]);
console.log(output);
You could use an odd way of using Array#reduce and Array#filter
First, filter out non-numeric
Second reduce this filtered array, with an initial value of 0 - if the array is zero length, reduce will return 0
function findSmallestNumberAmongMixedElements(arr) {
var smallestNum = Infinity;
return arr.filter(item => typeof item == 'number').reduce((min,item) => {
if(item < smallestNum) smallestNum = item;
return smallestNum;
}, 0);
}
console.log(findSmallestNumberAmongMixedElements([]));
console.log(findSmallestNumberAmongMixedElements(['1','2','3']));
console.log(findSmallestNumberAmongMixedElements([1,2,3]));
console.log(findSmallestNumberAmongMixedElements(['1',2,3]));

Categories