Find out the odd numbers from a given number - javascript

i was trying to solve a codewars kata where it is required to find the count of all the sequential odd-numbered substrings from a given string. Eg: for "1341", the output would be 7 (1, 3, 1, 13, 1341, 341, 41 - repetitions are allowed). The code I wrote below (agreeably not the most efficient) works well for a few test cases, however fails for the bigger numbers. Eg: it works well for '134721', however fails for '555564398422914589479591281194'. I'm a complete beginner, so any help be appreciated.
PS: test case numbers don't have '0', so haven't accounted for that yet.
function solve(s) {
let result = [];
for (let i = 0; i < s.length; i++) {
for (let j = 0; j <= s.length; j++) {
let required = s.slice(i, j);
if (required !== '' && required % 2 === 1) {
result.push(required);
}
}
}
return result.length;
}
solve(555564398422914589479591281194) //should return 280, my code is returning 210.

This is because of the Number.MAX_SAFE_INTEGER it's 9007199254740991 so the arithmetic it is not operating correctly.
Instead of verifying the whole number if it is odd, verify the last digit
function solve(s) {
let result = [];
for (let i = 0; i < s.length; i++) {
for (let j = 0; j <= s.length; j++) {
let required = s.slice(i, j);
if (required !== '' && required[required.length - 1] % 2 === 1) {
result.push(required);
}
}
}
return result.length;
}
solve("555564398422914589479591281194")

Related

Count Number of Teams - Javascript

I'm trying to solve the problem below in JavaScript.
There are n soldiers standing in a line. Each soldier is assigned a
unique rating value.
You have to form a team of 3 soldiers amongst them under the following
rules:
Choose 3 soldiers with index (i, j, k) with rating (rating[i],
rating[j], rating[k]). A team is valid if: (rating[i] < rating[j] <
rating[k]) or (rating[i] > rating[j] > rating[k]) where (0 <= i < j <
k < n). Return the number of teams you can form given the conditions.
(soldiers can be part of multiple teams).
Example:
Input: rating = [2,5,3,4,1]
Output: 3
Explanation: We can form three teams given the conditions. (2,3,4), (5,4,1), (5,3,1).
My idea is to keep an array of possible combinations, when I reach 3 elements in the combinations, I increment my res variable. My attempt:
var numTeams = function(rating) {
let res = 0;
if(!rating || rating.length < 3) return res;
let combinations = [];
for(let i=0; i<rating.length; i++) {
const size = combinations.length;
for(let j=0; j<size; j++) {
const temp = combinations[j];
if(temp.length === 1 && temp[0] !== rating[i]) {
temp.push(rating[i]);
combinations.push(temp);
} else {
if(temp[0] < temp[1] && temp[1] < rating[i])
res++;
else if(temp[0] > temp[1] && temp[1] > rating[i])
res++;
}
}
combinations.push([rating[i]]);
}
return res;
};
It is returning 2 for the example input, not 3.
I suggest to use three encapsulated for loops. By initializing the indexes with the value of the current value of the index of the outer loop, e.g. k = i, the condition (0 <= i < j < k < n) is implicitly fulfilled.
Within the innermost loop, you can then check if the conditions to be a combination is true for the current set of soldiers by checking if rating[i] < rating[k] && rating[k] < rating[l] or rating[i] > rating[k] && rating[k] > rating[l] and add the values to the array holding the valid combinations.
At the end, the length of the array holding the valid combinations is printed:
var rating = [2,5,3,4,1];
var combinations = [];
for (i = 0; i < rating.length; i = i+1) {
for (k = i; k < rating.length; k = k+1) {
for (l = k; l < rating.length; l = l+1) {
if (rating[i] < rating[k] && rating[k] < rating[l]) {
combinations.push([rating[i], rating[k], rating[l]]);
}
if (rating[i] > rating[k] && rating[k] > rating[l]) {
combinations.push([rating[i], rating[k], rating[l]]);
}
}
}
}
console.log(combinations);
console.log(combinations.length);
Output:
[ [ 2, 3, 4 ], [ 5, 3, 1 ], [ 5, 4, 1 ] ]
3
For better performance compared to the three for loops provided in answer https://stackoverflow.com/a/64921918/9240674, i also iterate over the rating array only once now. An array variations holds all variations that may become a valid combination. The entries consist of the function which is used to determine whether the variation is a valid combination and the ratings. With each iteration over the rating array, the new rating[i] is checked against all variations if it might complete the currently checked variation to become a valid combination. If so, the ratings of the current variation[k] are stored in combinations array.
var rating = [2,5,3,4,1];
var variations = [];
var combinations = [];
function less_than(a, b) {
return a < b;
}
function greater_than(a, b) {
return a > b;
}
for (i = 0; i < rating.length; i = i + 1) {
var duplications = [];
for (k = 0; k < variations.length; k = k + 1) {
if (variations[k].ratings.length < 3) {
if (variations[k].comparemethod(rating[i],variations[k].ratings[variations[k].ratings.length-1])) {
// Duplicate current (incomplete) variation
duplications.push({"comparemethod": variations[k].comparemethod, "ratings": variations[k].ratings.slice()});
// Add the current rating to the current variation
variations[k].ratings.push(rating[i]);
}
if (variations[k].ratings.length == 3) {
// we found a valid combination
combinations.push(variations[k].ratings);
}
}
}
// add entries which needed to be duplicated to the variations
variations = variations.concat(duplications);
// add the current rating to the variations
variations.push({comparemethod: less_than, ratings: [rating[i]]});
variations.push({comparemethod: greater_than, ratings: [rating[i]]});
}
console.log(JSON.stringify(combinations));
console.log(combinations.length);
Output:
[[2,3,4],[5,3,1],[5,4,1]]
3

Why my "Repeated Strings" code isn't working? || Hackerrank || JavaScript

((s, n) => {
let nStrings = ''; // stores the string we get after multiplying s to reach length n.
let aNos = 0; // stores the number of 'a's present in nStrings;
for (let i = 0; i < n; i++) {
for (let j = 0; j < s.length; j++) {
if (nStrings.length === n) {
break;
} else {
nStrings += s[j];
}
}
}
for (let k = 0; k < nStrings.length; k++) {
if (nStrings[k] === 'a') {
aNos++;
}
}
return aNos;
})('a', 1000000000000);
Above is my code written for the problem "Repeated Strings" in Hackerrank (Problem link). I wrote this in JavaScript. When I ran this code it shows that it ran out of memory. I don't understand why.
Please review my code and let me know why it failed.
Thank you.
You could get the the count of a in the given string, divide the length by the string length, get the integer part and multiply with the count of the given string.
The second part is to get the rest of the wanted length with remainder operator and iterate the given string for getting a count of a.
Return the sum of the integer and rest count.
function getCount(string, length) {
var first = 0,
count = 0,
rest = 0,
restCount = 0,
i;
for (i = 0; i < string.length; i++) if (string[i] === 'a') count++;
first = Math.floor(length / string.length) * count;
rest = length % string.length;
for (i = 0; i < rest; i++) if (string[i] === 'a') restCount++;
return first + restCount;
}
console.log(getCount('aba', 10)); // 7

How do I utilize the length of an array in a function (in JavaScript) when the array is being passed as a parameter and the length does not exist yet?

I'm trying to write a function that takes an array of strings(strarr) and an integer(k) as parameters and returns the longest string made up of k amount of consecutive strings within the array, not separated by commas. I need to call on strarr.length quite often during the function, but I keep getting an error saying that it cannot read that parameter's length.
This is my first time dealing with this issue and I have not found great internet search results for solutions. I suspect that I'm missing something very obvious. I have tried pushing the values of the strarr array parameter into a new array and still no luck.
So if I had const = ['apple','pineapple','banana','strawberry'] passed as my strarr parameter and 2 passed as k, then it should return 'bananastrawberry' because it is the longest consecutive pair of strings within the array.
const arr = ['apple', 'pineapple', 'banana', 'strawberry']
function longestConsec(strarr, k) {
if (strarr.length === 0) {
return "";
} else if (k > strarr.length) {
return "";
} else if (k <= 0) {
return "";
}
let longest = "";
let strLeng = 0;
for (let i = 0; i < strarr.length; i++) {
for (let j = i + (k - 1); j > 0; j--) {
strLeng += strarr[j].length;
}
if (strLeng > longest.length) {
longest = strarr.slice(i, (i + k)).join("");
}
}
return longest;
}
console.log(longestConsec(arr, 2))
As mentioned, you are trying to access an index that doesn't exist in you array.
A quick fix might be:
const arr = ['apple', 'pineapple', 'banana', 'strawberry']
function longestConsec(strarr, k) {
if (strarr.length === 0) {
return "";
} else if (k > strarr.length) {
return "";
} else if (k <= 0) {
return "";
}
let longest = "";
let strLeng = 0;
for (let i = 0; i < strarr.length; i++) {
for (let j = i + (k - 1); j > 0; j--) {
if (j >= strarr.length) {
break;
}
strLeng += strarr[j].length;
}
if (strLeng > longest.length) {
longest = strarr.slice(i, (i + k)).join("");
}
}
return longest;
}
console.log(longestConsec(arr, 2))
But I would suggest to see if there is better solution than adding a break statement.
Mistakes you did
In the inner for loop, for (let j = i + (k - 1); j > 0; j--), you're counting from i + k - 1. But what if i is the last index of array (strarr.length == 10 and i == 9) and k == 2? Then your loop starts at j = 9 + 2 - 1 = 10 and one line below, you try to do strLeng += strarr[10].length, but strarr[10] is not defined.
It also seems unnecessary to create strings before you're done finding the longest one. You could instead just remember start index of your last longest string instead.
How to make it better
Let's look at the requirements. For each i in the array, you want to merge k consecutive strings and keep the longest combination. From that follows:
i + k - 1 must never be larger than strarr.length. Since the i is the only variable here, we need to limit it by only looping up to strarr.length - k + 1.
If k == strarr.length, there is only one string you can make - strarr.join("")
Finally, there's an idea that you probably do not need nested loop at all. For every i, you simply subtract the length of the last string in your current window and add a new one. See image:
So with that in mind, I would propose following version of your code:
function longestConsec(strarr, k) {
// Cannot create any joined string with k greater than length
if(strarr.length < k) {
return "";
}
else if(k <= 0) {
return "";
}
else if(strarr.length == k) {
return strarr.join("");
}
let longestIndex = -1;
let longestLength = 0;
// length of our current group of strings
let currentLength = 0;
const maxLen = strarr.length;
for(let i=0; i<maxLen; ++i) {
// Forget the first strings length
if(i >= k) {
currentLength -= strarr[i-k].length;
}
// add the current strings length
currentLength += strarr[i].length;
// check if this is the largest length and save it's index
// Only possible after processing at least k strings
// Eg when i==1, we already went through 2 strings at this point
if(i >= k-1) {
if(currentLength > longestLength) {
const startIndex = i-k+1;
longestLength = currentLength;
longestIndex = startIndex;
}
}
}
return strarr.slice(longestIndex, (longestIndex + k)).join("");
}
Here's a jsFiddle test: https://jsfiddle.net/32g5oqd1/2/

Code works in console but not in Hackerank

My code works in console but gives the wrong result in hackerank
Problem: Print count of all substrings that are palindromes from a string
function isPalindrome(str) {
var len = str.length;
var mid = Math.floor(len / 2);
for (var i = 0; i < mid; i++) {
if (str[i] !== str[len - 1 - i]) {
return false;
}
}
//Had to use this lengthy function because in
//str == str.split('').reverse().join('');
//I was getting error that split is not a function
return true;
}
function scatterPalindrome(str) {
var result = [],
c = 0;
for (let i = 0; i < str.length; i++) {
for (let j = i + 1; j < str.length + 1; j++) {
result.push(str.slice(i, j));
}
}
for (let i = 0; i < result.length; i++) {
let k = result[i];
if (isPalindrome(k))
c++;
}
return c; // the answer was always 1
}
console.log(scatterPalindrome("abc"));
input: "abc"
expected output: 3
actual output:1
As I can't comment, so answering here, I will say you should check if they have mentioned there are many test cases, and in each test case you have to do the query then this is reasonable that your output and their output will not match
take no.of testcases input
while(testcases counter doesn't reach 0 )
take string input
call your function for answer for input and print
decrement testcases counter

Code to display all prime numbers not working in JavaScript?

I'm trying to display all the prime numbers up to 10 and it isn't working. Can you see what I did wrong?
function findPrimeNumbers() {
var count = 10,
primes = [];
for (var i = 0; i <= count; i++) {
if (count / i === 1 || count) primes.push(i);
else continue;
count -= 1;
}
for (var i = 0, len = primes.length; i < len; i++) return primes[i];
}
console.log(findPrimeNumbers());
It only returns 0 in the console.
Here's about the simplest way to generate primes. Note that there are more efficient methods, but they are harder to understand.
function findPrimeNumbers (count) {
var primes = [];
for (var J = 2; J <= count; J++) {
var possPrime = true;
for (var K = 2, factorLim = Math.sqrt (J); K <= factorLim; K++) {
if (J % K == 0) {
possPrime = false;
break;
}
}
if (possPrime)
primes.push (J);
}
return primes;
}
console.log (findPrimeNumbers (10) );
This yields all the primes <= 10:
[2, 3, 5, 7]
See Wikipedia for an explanation.
for (var i = 0, len = primes.length; i < len; i++) return primes[i];
Here you are return just the first element of the array. I think you meant something like this
var retstr = "";
for (var i = 0, len = primes.length; i < len; i++)
{
//To improve str format
if(i == len-1)
retstr += primes[i];
else
retstr += primes[i] + ", ";
}
return retstr;
Hope this helps.
if (count / i === 1 || count / i === count)
You don't say how it's not working, but the first thing that comes to my attention is that you're incrementing i, while at the same time decrementing count, so i will never get all the way to 10.
Also, count / i will cause a divide-by-zero error on the first iteration as it's written (unless Javascript magically handles that case in some way I'm not familiar with).
Then you "loop" through your return values--but you can only return once from a function, so of course you're only going to return the first value.
And you are returning from the function in the last for loop. Remove that for loop, just return the array.
function PrimeCheck(n){ //function to check prime number
for(i=2;i<n;i++){
if(n%i==0){
return false
}
}
return true;
}
function print(x){ //function to print prime numbers
var primeArray=[];
for(j=2;j<x;j++){
if(PrimeCheck(j)==true){
primeArray.push(j);
}
}
console.log(primeArray);
}
print(10); //[2,3,5,7]

Categories

Resources