How to reverse a string in a specific way - javascript

This is a very specific question and I want to reverse a string in this way however I don't know how to go about it.
What i want to do is take a word lets say 'hello'. olleh
and take the first and last letters and output 'oellh' then doing the same thing for the next two characters so 'e' and 'l' which would then output 'olleh'.
So to summaries this I need to reverse the first and last character and then the same thing for the second characters until i get to the middle character.
This must use a for loop.
reverse('hello');
function reverse(string) {
var character = [];
for (var i = string.length -1; i >= 0; i--) {
character.push(string[i]);
}
console.log(character.join(""));
}
Let me know if this needs further explanation

This might do the trick:
function replaceAt(string, index, character){
return string.substr(0, index) + character + string.substr(index+character.length);
}
function reverse(string) {
var len = string.length;
len = len/2;
var s = string;
for (var i = 0; i < len ; i++)
{
var m = s[string.length-i-1];
var k = s[i];
s = replaceAt(s,i, m);
s = replaceAt(s, string.length-i-1, k);
}
return s;
}

You can easily reverse a string doing:
"hello".split("").reverse().join("")

Related

Find Longest Prefix That is Also a Suffix in String - Javascript

Link to codewars challenge
I need to return the length of the longest prefix that is also a suffix of a string in Javascript.
As far as I understand, the prefixes in "abcd" are:
['a', 'ab', 'abc']
And the suffixes in "abcd" are:
[ 'bcd', 'cd', 'd' ]
So the length of the longest prefix that is also a suffix in "abcd" in this case is 0, because there are no prefixes that are also suffixes in "abcd".
So far I've been able to figure out how to get the suffixes into an array for comparison, but not the prefixes.
function returnLongestPrefixAndSuffix(string) {
let prefixes = [];
let suffixes = [];
for (let i = 0; i < string.length -1; i++) {
prefixes.push(string.slice(i));
}
for (let i = 1; i < string.length; i++) {
suffixes.push(string.slice(i));
}
return prefixes + " " + suffixes;
}
console.log(returnLongestPrefixAndSuffix("abcd"));
I'm not grasping the concept of how to start at the beginning of a string and add a larger element to the array each time by one character, excluding the element that would include the last one.
Please follow my current logic if possible.
EDIT: My code now looks like this:
function solve(string) {
let prefixes = [];
let suffixes = [];
let includedList = [];
for (let i = 1; i < string.length; i++) {
prefixes.push(string.slice(0, i));
}
for (let i = 1; i < string.length; i++) {
suffixes.push(string.slice(-i));
}
console.log(prefixes);
console.log(suffixes);
for (let i = 0; i < prefixes.length; i++) {
let element = prefixes[i];
if (suffixes.includes(element) === true) {
includedList.push(element);
}
}
console.log(includedList);
if (includedList.length === 0) {
return 0;
}
else {
let overlap = prefixes.filter(value => suffixes.includes(value));
console.log(overlap);
let longest = includedList.sort(function (a, b) { return b.length - a.length; })[0];
return longest.length;
}
}
console.log(solve("abcdabc"));
And this is passing 10049 test but failing 163 tests on codewars. I still do not know what to do with the overlap variable or how to exclude overlaps from the includedList array.
function solve(string) {
for (let i = Math.floor(string.length / 2); i > 0; i--) {
let prefix = string.slice(0, i);
let suffix = string.slice(-i);
if (prefix == suffix) {
return i;
}
}
return 0;
}
console.log(solve("abcdabc"));
To account for the overlap, initialize your for-loop like this:
let i = Math.floor(string.length / 2)
That will initialize the for-loop at the half-way point in your string, so that you can count down and compare whether or not the prefix == the suffix, starting with the longest.
You could return prefix.length, but that will be the same thing as i.
Also, be sure to return 0 outside of the for-loop. Because if you try:
if (prefix != suffix) {
return 0;
}
inside of the for-loop, it will stop counting right there.
To get the prefixes, you can use the second argument of .slice:
string.slice(0, i)
Note that to get the suffixes, you could also take the string from the end:
string.slice(-i)
There is no sense in collecting prefixes and suffixes in arrays, just search for the biggest i where the suffix equals the prefix.
Please see the documentation of the slice function, it may take a second argument: https://www.w3schools.com/jsref/jsref_slice_string.asp
So following your logic, one way to get prefixes would be to:
for (let i = 1; i <= string.length; i++) {
prefixes.push(string.slice(0, i));
}
EDIT:
Your newest code doesn't work because of two reasons:
You may end up with includedList being empty, but you still try to get first element out of it.
You don't take overlaps into consideration. For the input aaa the correct result is a since prefix aa overlaps with the corresponding suffix. In other words the result can't be longer than half the length of the input.

How to make element in Array change its' place

I'm beginner in JS. I've tried to understand Caesar Cipher ROT13, but it was too complicated for me. So I've tried to write my own code. Here it is below:
function encrip() {
var alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var str = "Ni Hao";
var string = str.toUpperCase();
for (var i = 0; i < string.length; i++) {
for (var k = 0; k < alphabet.length; k++) {
if(string.charAt(i) == alphabet[k]) {
/* console.log(string.charAt(i) + ' ' + alphabet.indexOf(alphabet[k])); */
}
}
}
}
encrip();
But I am stuck. How to do:
1. Get value from var str and then access to var alphabet , after change each letter from var str value to next 3 from alphabet (var str each element's current position would be changed) For example: Input: Ni Hao ==> output: QL KDR
2. Create universal code, I mean, not only for changing position by 3, but when I give value '5', each element would be changed by next 5 positions from alphabet. So output can be changed when I change its' value
I hope I explained everything clearly. Thanks everyone in advance for help!!
you can use the following function to encrypt english words, the 1st parameter is the string to encrypt and the 2nd for shifting
function encryp(str,pos){
var alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var strUC=str.toUpperCase();
var enc="";
for(var i=0;i<strUC.length;i++){
if(strUC.charAt(i)!=" "){
enc+=alpha.charAt((alpha.indexOf(strUC.charAt(i))+pos)%26)
}
else{
enc+=" "
}
// in your case pos=3
}
return enc;
}
console.log(encryp("NiHao",3));
You don't need two for loops to do this. Iterate over the input string and find the index of each character in the alphabet array, if found add the shift to it to get the encrypted character.
To handle overflow use the modulus operator to cycle through the array.
Also I assume that you are not going use any special symbols to do the encryption.
function encrip(string, shift) {
var alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
string = string.toUpperCase();
let arr = [];
for (var i = 0; i < string.length; i++) {
let char = alphabet.indexOf(string[i]) !== -1 ? alphabet[(alphabet.indexOf(string[i]) %26) + shift] : " ";
arr.push(char);
}
let encryp = arr.join("");
console.log(encryp);
return encryp;
}
encrip("Ni Hao", 3);
First of all, instead of your inner for loop scanning the whole alphabet array, you can use the built-in function indexOf:
alphabet.indexOf('K') // returns 10
Secondly, you'll want to build up your enciphered string in a separate variable. For each letter, get the index of that letter in the alphabet, add your cipher offset parameter to that index and add the resulting letter from the alphabet to your new string. An important step is that when you add to the index of the letter, you want to make sure the resulting index is within range for the alphabet array. You can do that using the % (modulo) operator, which will wrap high values back round to the start of the array. In full:
function encipher(input, offset) {
var alphabet = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"];
var str = input.toUpperCase();
var result = '';
for (var i = 0; i < str.length; i++) {
letterIndex = alphabet.indexOf(str.charAt(i));
if (letterIndex === -1) {
result += str[i]; // if the letter isn't found in the alphabet, add it to the result unchanged
continue;
}
cipheredIndex = (letterIndex + offset) % alphabet.length; // wrap index to length of alphabet
result += alphabet[cipheredIndex];
}
console.log(result);
}
encipher('Ni Hao', 5); // output: 'SN MFT'

Whats wrong with my palindrome? (javascript)

I have written this js code for palindrome, I know there are better and more efficient palindrome methods online but I want to know why I am unable to get my palindrome function to work properly?
CODE:
var pal = function(str) {
var len = str.length;
for (var i = 0; i < len; i++) {
var comp1 = str.substring(i, i + 1);
for (var j = len; j > 0; j--) {
var comp2 = str.substring(j - 1, j);
}
if (comp1 != comp2) {
console.log("not palindrome")
break;
} else {
console.log('palindrome')
}
}
}
pal('maddog');
OUTPUT :
palindrome
not palindrome
There are lot of better algorithms to check Palindrome. Let use the similar algorithm that you are using.
We basically use two pointers - left and right, and move to middle at the same time. In the original question, left pointer and right pointer doesn't move at the same time.
Pointers should move like this -
a b c b a
^ ^
a b c b a
^ ^
a b c b a
^
var isPalindrome = function (str) {
for (var i = 0, j = str.length-1; i < j; i++ , j--) {
if (str[i] != str[j]) {
return false;
}
}
return true;
}
console.log('maddog : ' + isPalindrome('maddog'));
console.log('abcba : ' + isPalindrome('abcba'));
console.log('deed : ' + isPalindrome('deed'));
console.log('a : ' + isPalindrome('a'));
Try the following code. It works by dividing the string length by 2, and then iterating up, checking mirroring characters against each other:
var pal = function(str){
var len = str.length;
for(var i = 0; i < Math.floor(len/2); i++){
if(str[i] != str[(len-1)-i]){
return false;
}
}
return true;
}
console.log(pal("bunny"));
console.log(pal("amoreroma"));
The inner loop is totally unnecessary. It does the same thing every time -- it loops through the whole string, starting from the end, repeatedly setting comp2 to the character; when it's done, comp2 always contains the first character. So your function just tests whether every character in the string is the same as the first character.
To test if something is a palindrome, you need to compare each character with the corresponding character from the other end of the string. You don't need two loops for this. You also only need to loop through the first half of the string, not the whole string.
Finally, you should only echo Palindrome at the end of the loop. Inside the loop you only know that one character matches, not all of them.
var pal = function(str) {
var len = str.length;
var half = Math.floor(len / 2);
var isPal = true;
for (var i = 0; i < half; i++) {
var comp1 = str[i];
var comp2 = str[len - i - 1];
if (comp1 != comp2) {
console.log("not palindrome")
isPal = false;
break;
}
}
if (isPal) {
console.log('palindrome')
}
}
pal('maddog');
pal('maddam');
You don't really need the nested loops, you can just loop backwards through the string to invert the string and then compare it to the original string. I updated the Snippet to work.
Before, your code was not inverting the string but rather just iterating through the characters and assigning them to the comp1 and comp1 variables. You need to concatenate the strings in order to build the new string backwards comp = comp + str.substring(j-1, j);
var pal = function(str) {
var len = str.length;
var comp = '';
for (var j = len; j > 0; j--) {
comp = comp + str.substring(j - 1, j);
}
if (str !== comp) {
console.log("not palindrome")
return;
}
console.log('palindrome')
}
pal('arepera');

Return the first word with the greatest number of repeated letters

This is a question from coderbyte’s easy set. Many people asked about it already, but I’m really curious about what’s wrong with my particular solution (I know it’s a pretty dumb and inefficient one..)
Original question:
Have the function LetterCountI(str) take the str parameter being passed and return the first word with the greatest number of repeated letters. For example: "Today, is the greatest day ever!" should return greatest because it has 2 e's (and 2 t's) and it comes before ever which also has 2 e's. If there are no words with repeating letters return -1. Words will be separated by spaces.
My solution works most of the time. But if it seems the last word of the input isn’t valued by my code. For example, for “a bb ccc”, “bb” will be returned instead of “ccc”. But the funny thing here is if the string only contains one word, the result is correct. For example, “ccc” returns “ccc”.
Please tell me where I was wrong. Thank you in advance!
function LetterCountI(str) {
str.toLowerCase();
var arr = str.split(" ");
var count = 0;
var word = "-1";
for (var i = 0; i < arr.length; i++) {
for (var a = 0; a < arr[i].length; a++) {
var countNew = 0;
for (var b = a + 1; b < arr[i].length; b++) {
if(arr[i][a] === arr[i][b])
countNew += 1;
}
if (countNew > count) {
count = countNew;
word = arr[i];
}
}
return word;
}
}
Please find below the workable version of your code:
function LetterCountI(str) {
str = str.toLowerCase();
var arr = str.split(" ");
var count = 0;
var word = "-1";
for (var i = 0; i < arr.length; i++) {
for (var a = 0; a < arr[i].length; a++) {
var countNew = 0;
for (var b = a + 1; b < arr[i].length; b++) {
if (arr[i][a] === arr[i][b])
countNew += 1;
}
if (countNew > count) {
count = countNew;
word = arr[i];
}
}
}
return word;
}
Here is the Java code soln for your problem.
You have returned your answer incorrectly. You should have returned word/Answer/res out of "for loops".
Check my chode here.
public static String StringChallenge( String str) {
String[] arr = str.split(" ");
int count = 0; String res = "-1";
for (int i = 0; i < arr.length ; i++) {
for (int j = 0; j < arr[i].length() ; j++) {
int counter = 0;
for (int k = j + 1; k < arr[i].length() ; k++) {
if(arr[i].charAt(j) === arr[i].charAt(k) )
counter ++;
}
if (counter > count) {
count = counter; res = arr[i];
}
}
return res;
}
}
I think the problem is that you're placing the return statement inside your outermost loop. It should be inside your inner loop.
So you have to place the return statement within the inner loop.
Correct use of return
if (countNew > count) {
count = countNew;
word = arr[i];
}
return word;
}
}
}
You need to move the return word; statement outside of the loop to fix your version.
I also put together another take on the algorithm that relies on a few built in javascript methods like Array.map and Math.max, just for reference. I ran a few tests and it seems to be a few milliseconds faster, but not by much.
function LetterCountI(str) {
var maxCount = 0;
var word = '-1';
//split string into words based on spaces and count repeated characters
str.toLowerCase().split(" ").forEach(function(currentWord){
var hash = {};
//split word into characters and increment a hash map for repeated values
currentWord.split('').forEach(function(letter){
if (hash.hasOwnProperty(letter)) {
hash[letter]++;
} else {
hash[letter] = 1;
}
});
//covert the hash map to an array of character counts
var characterCounts = Object.keys(hash).map(function(key){ return hash[key]; });
//find the maximum value in the squashed array
var currentMaxRepeatedCount = Math.max.apply(null, characterCounts);
//if the current word has a higher repeat count than previous max, replace it
if (currentMaxRepeatedCount > maxCount) {
maxCount = currentMaxRepeatedCount;
word = currentWord;
}
});
return word;
}
Yet another solution in a more functional programming style:
JavaScript
function LetterCountI(str) {
return ((str = str.split(' ').map(function(word) {
var letters = word.split('').reduce(function(map, letter) {
map[letter] = map.hasOwnProperty(letter) ? map[letter] + 1 : 1;
return map;
}, {}); // map of letters to number of occurrences in the word
return {
word: word,
count: Object.keys(letters).filter(function(letter) {
return letters[letter] > 1;
}).length // number of repeated letters
};
}).sort(function(a, b) { // Sort words by number of repeated letters
return b.count - a.count;
}).shift()) && str.count && str.word) || -1; // return first word with maximum repeated letters or -1
}
console.log(LetterCountI('Today, is the greatest day ever!')); // => greatest
Plunker
http://plnkr.co/edit/BRywasUkQ3KYdhRpBfU2?p=preview
I recommend use regular expression: /a+/g to find a list of letter with a key word a.
My example :
var str = aa yyyyy bb cccc cc dd bbb;
Fist, find a list of different word :
>>> ["a", "y", "b", "c", "d"]
Use regular expression for each word in list of different word :
var word = lstDiffWord[1];
var
wordcount = str.match(new RegExp(word+'+','g'));
console.log(wordcount);
>>>>["yyyyy"]
Here is full example: http://jsfiddle.net/sxro0sLq/4/

Counting vowels in javascript

I use this code to search and count vowels in the string,
a = "run forest, run";
a = a.split(" ");
var syl = 0;
for (var i = 0; i < a.length - 1; i++) {
for (var i2 = 0; i2 < a[i].length - 1; i2++) {
if ('aouie'.search(a[i][i2]) > -1) {
syl++;
}
}
}
alert(syl + " vowels")
Obviously it should alert up 4 vowels, but it returns 3.
What's wrong and how you can simplify it?
Try this:
var syl = ("|"+a+"|").split(/[aeiou]/i).length-1;
The | ensures there are no edge cases, such as having a vowel at the start or end of the string.
Regarding your code, your if condition needs no i2
if('aouie'.search(a[i]) > -1){
I wonder, why all that use of arrays and nested loops, the below regex could do it better,
var str = "run forest, run";
var matches = str.match(/[aeiou]/gi);
var count = matches ? matches.length : 0;
alert(count + " vowel(s)");
Demo
Try:
a = "run forest, run";
var syl = 0;
for(var i=0; i<a.length; i++) {
if('aouie'.search(a[i]) > -1){
syl++;
}
}
alert(syl+" vowels")
First, the split is useless since you can already cycle through every character.
Second: you need to use i<a.length, this gets the last character in the string, too.
The simplest way is
s.match(/[aeiou]/gi).length
You can use the .match to compare a string to a regular expression. g is global which will run through the entire string. i makes the string readable as upper and lower case.
function getVowels(str) {
var m = str.match(/[aeiou]/gi);
return m === null ? 0 : m.length;
}

Categories

Resources