Why my "Repeated Strings" code isn't working? || Hackerrank || JavaScript - 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

Related

Find out the odd numbers from a given number

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

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

JavaScript Permutations

I am trying to count the number of permutations that do not contain consecutive letters. My code passes tests like 'aabb' (answer:8) and 'aab' (answer:2), but does not pass cases like 'abcdefa'(my answer: 2520; correct answer: 3600). Here's my code:
function permAlone(str) {
var totalPerm = 1;
var result = [];
//assign the first letter
for (var i = 0; i < str.length; i++) {
var firstNum = str[i];
var perm = firstNum;
//create an array from the remaining letters in the string
for (var k = 0; k < str.length; k++) {
if (k !== i) {
perm += str[k];
}
}
//Permutations: get the last letter and change its position by -1;
//Keep changing that letters's position by -1 until its index is 1;
//Then, take the last letter again and do the same thing;
//Keep doing the same thing until the total num of permutations of the number of items in the string -1 is reached (factorial of the number of items in the string -1 because we already established what the very first letter must be).
var permArr = perm.split("");
var j = permArr.length - 1;
var patternsLeft = totalNumPatterns(perm.length - 1);
while (patternsLeft > 0) {
var to = j - 1;
var subRes = permArr.move(j, to);
console.log(subRes);
if (noDoubleLettersPresent(subRes)) {
result.push([subRes]);
}
j -= 1;
if (j == 1) {
j = perm.length - 1;
}
patternsLeft--;
}
}
return result.length;
}
Array.prototype.move = function(from, to) {
this.splice(to, 0, (this.splice(from, 1))[0]);
return this.join("");
};
function totalNumPatterns(numOfRotatingItems) {
var iter = 1;
for (var q = numOfRotatingItems; q > 1; q--) {
iter *= q;
}
return iter;
}
function noDoubleLettersPresent(str) {
if (str.match(/(.)\1/g)) {
return false;
} else {
return true;
}
}
permAlone('abcdefa');
I think the problem was your permutation algorithm; where did you get that from? I tried it with a different one (after Filip Nguyen, adapted from his answer to this question) and it returns 3600 as expected.
function permAlone(str) {
var result = 0;
var fact = [1];
for (var i = 1; i <= str.length; i++) {
fact[i] = i * fact[i - 1];
}
for (var i = 0; i < fact[str.length]; i++) {
var perm = "";
var temp = str;
var code = i;
for (var pos = str.length; pos > 0; pos--) {
var sel = code / fact[pos - 1];
perm += temp.charAt(sel);
code = code % fact[pos - 1];
temp = temp.substring(0, sel) + temp.substring(sel + 1);
}
console.log(perm);
if (! perm.match(/(.)\1/g)) result++;
}
return result;
}
alert(permAlone('abcdefa'));
UPDATE: In response to a related question, I wrote an algorithm which doesn't just brute force all the permutations and then skips the ones with adjacent doubles, but uses a logical way to only generate the correct permutations. It's explained here: Permutations excluding repeated characters and expanded to include any number of repeats per character here: Generate all permutations of a list without adjacent equal elements
I agree with m69, the bug seems to be in how you are generating permutations. I got 3600 for 'abcdefa' by implementing a different algorithm for generating permutations. My solution is below. Since it uses recursion to generate the permutations the solution is not fast, however you may find the code easier to follow, if speed is not important.
The reason for having a separate function to generate the array index values in the permutations was to verify that the permutation code was working properly. Since there are duplicate values in the input strings it's harder to debug issues in the permutation algorithm.
// Simple helper function to compute all permutations of string indices
function permute_indices_helper(input) {
var result = [];
if (input.length == 0) {
return [[]];
}
for(var i = 0; i < input.length; i++) {
var head = input.splice(i, 1)[0];
var tails = permute_indices_helper(input);
for (var j = 0; j < tails.length; j++) {
tails[j].splice(0, 0, head);
result.push(tails[j]);
}
input.splice(i, 0, head); // check
}
return result;
};
// Given an array length, generate all permutations of possible indices
// for array of that length.
// Example: permute_indices(2) generates:
// [[0,1,2], [0,2,1], [1,0,2], ... , [2, 0, 1]]
function permute_indices(array_length) {
var result = [];
for (var i = 0; i < array_length; i++) {
result.push(i);
}
return permute_indices_helper(result);
}
// Rearrange letters of input string according to indices.
// Example: "car", [2, 1, 0]
// returns: "rac"
function rearrange_string(str, indices) {
var result = "";
for (var i = 0; i < indices.length; i++) {
var string_index = indices[i];
result += str[string_index];
}
return result;
}
function permAlone(str) {
var result = 0;
var permutation_indices = permute_indices(str.length);
for (var i = 0; i < permutation_indices.length; i++) {
var permuted_string = rearrange_string(str, permutation_indices[i]);
if (! permuted_string.match(/(.)\1/g)) result++;
}
return result;
}
You can see a working example on JSFiddle.

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