Need help building a caesar cipher project - javascript

I have a code, that takes a string, it converts to array and using split(''), i have a for loop that search the element in the alphabet array i created, i need to change the index of the element searched
Here is the code :
let 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"];
function caesar (str, plusIndex) {
for (let i = 0; i < str.length; i++) {
let divided = str.split('') // split the string into a array
let indexes = alphabet.indexOf(divided[i]); //shows the index of each divided element in alphabet
}
}
caesar("hey") // this show 7,4,24 in each iteration
I need to change this like
caesar("hey", 3) show something like 10,7,27 and return the element of that indexes
hey,3 should output m,j,d
i tried using another string, charCodeAt, charAt, but i cant convert the index into a different index

Considering you're only using lower case alphabets. You don't need an array, you can just use the ascii numbers. (97 - 122 => a - z)
Then in your function caeser(string, key) split the string as you currently are, and for each letter =>
int offset = (int(letter) + key)%26;
int cipher = char(97+(26-offet-1));
cipher is your required letter.
Now 97 is position of a in ascii. 26 is number of alphabets. The -1 in offset - 1 is done to include the 97th ascii position ( a ) in calculation

let 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"];
function caesar (str, plusIndex) {
let encrypted = [] //create an array to store the new word
for (let i = 0; i < str.length; i++) {
let divided = str.split('')
let indexes = (alphabet.indexOf(divided[i]) + plusIndex)%alphabet.length; //Get the index of the current letter, add the shift and loop back to start if the index is out of bounds
encrypted.push(alphabet[indexes]) //add the new letter to the encrypted array
}
return(encrypted)
}
caesar("hey", 8)
Be aware that this will only work for characters that are in your "alphabet" variable.

let 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"];
function caesar (str, plusIndex) {
let ans = ""
for (let i = 0; i < str.length; i++) {
let oldIndex = alphabet.findIndex(item => item === str[i])
let newIndex = (oldIndex + plusIndex) % alphabet.length
ans = ans + alphabet[newIndex]
}
return ans
}
let ans = caesar("hey",3)
console.log(ans) #shows khb
if you want just indexes use this:
let 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"];
function caesar (str, plusIndex) {
let ans = ""
for (let i = 0; i < str.length; i++) {
let oldIndex = alphabet.findIndex(item => item === str[i])
let newIndex = (oldIndex + plusIndex) % alphabet.length
ans = ans + newIndex + " "
}
return ans
}
let ans = caesar("hey",3)
console.log(ans) # shows 10 7 1

Related

expand a string in JavaScript to display letter and how many times that letter appears

Write a function that accepts a string where letters are grouped together and returns new string with each letter followed by a count of the number of times it appears.
example : ('aeebbccd') should produce // 'a1e2b2c2d1'
function strExpand(str) {
let results = ""
for (let i = 0; i < str.length; i++) {
let charAt = str.charAt(i)
let count = 0
results += charAt
for (let j = 0; j < str.length; j++) {
if (str.charAt(j) === charAt) {
count++;
}
}
results += count;
}
return results;
}
with the input 'aeebbccd' I am getting 'a1e2e2b2b2c2c2d1' instead of 'a1e2b2c2d1'
This function is adding a number after each character, which is the number of times this character appears anywhere in the string. You could instead do it like this to get the result you want.
function strExpand(str) {
let output = "";
// Iterate through each character of the string, appending
// to the output string each time
for (let i = 0; i < str.length; i++) {
let count = 1;
// If the next character is the same, increase the count
// and increment the index in the string
while (str[i + 1] == str[i]) {
count++;
i++;
}
// Add the character and the count to the output string
output += str[i] + count;
}
return output;
}
For sake of completeness,
how about a Regex?
const pattern = /(.)\1*/g; // put a char that exists in a capture group, then see if it repeats directly after
const s = 'aeebbccd';
var result = '';
for (match of s.match(pattern)) {
let this_group = match;
let this_len = match.length;
result = result + this_group[0] + this_len; // get only the first letter from the group
}
console.log(result); // a1e2b2c2d1
This would to the job. edit: hah i see im late :D, but still nice functional way to solve that.
/**
* #param string to count
* #return string $characterA$count. ex. abbccc -> a1b2c3
*/
function toCharacterCountString(str) {
return Array.from(new Set(str).values())
.map(char => {
return `${char}${(str.match(new RegExp(char, "g")) || []).length}`;
}).join('');
}
console.log(toCharacterCountString('abbccc')); // a1b2c3
console.log(toCharacterCountString('aeebbccd')); // a1e2b2c2d1

How can I know if the characters of a string repeat themselves the same amount of times when they have a wildcard built-in?

examples:
testing("xyzy**") should be true.
testing("xyzy*") should be false.
Reasoning:
In the first case, it is true because one * can behave as a x and the other a z, so all characteres would of the same amount of y.
In the second case there wouldn't be the same amount of characters repeating itself, cause there is only one *, so it is false.
Here is what I have up until now:
const testing = string => {
var array = []; //array with each character without repeating
var array_R = []; //array with the value the value that each character repeats itself
var array_C = 0; //counter for the size of "array"
//getting the character without repeating
for (var i = 0; i < string.length; i++) {
if (!array.includes(string.charAt(i))) {
array[array_C] = string.charAt(i);
array_R[array_C] = 0;
array_C++;
}
}
//how many each character repeats itself
for (var i = 0; i < array.length; i++) {
for (var j = 0; j < string.length; j++) {
if(array[i] == string.charAt(j)){
array_R[i] = array_R[i] + 1;
}
}
}
}
I really don't know how I can proceed from here.
First count up the number of occurrences of each non-* character into an object or Map. Find the maximum value in that collection, then find the sum of all differences between the maximum value and each value. If the number of asterisks is the same as the sum of differences, the repeat conditions are fulfilled.
You'll also have to consider the case where there are more asterisks left over after all holes are filled in to make the values equal - figure out how many are left over, and see if that evenly divides the number of separate characters.
const testing = (str) => {
const grouped = {};
for (const char of str) {
if (char !== '*') grouped[char] = (grouped[char] || 0) + 1;
}
const values = Object.values(grouped);
const numOfSeparateChars = values.length;
const max = Math.max(...values);
const sum = values.reduce((a, b) => a + b, 0);
const sumOfDifferencesFromMax = max * numOfSeparateChars - sum;
const numberAsterisks = (str.match(/\*/g) || []).length;
const remainingAsterisks = sumOfDifferencesFromMax - numberAsterisks;
// Now all characters have been filled in to make the values even
// eg: 'abcc**' -> 'abccab'
// But there may be more asterisks
// eg: 'abcc*****' -> 'abccaabbc'
return remainingAsterisks % numOfSeparateChars === 0;
};
console.log(testing("xyzy**"));
console.log(testing("xyzy*"));

want to get a count of repeated values on an array [duplicate]

This question already has answers here:
JavaScript function to automatically count consecutive letters in a string
(5 answers)
Closed 1 year ago.
I am a beginner in javascript, I want to get a count of repeated values on an array
I have a string "aaaaaabbbbbbbcccccccaa" and I want the output array be like ["a6", "b7", "c7", "a2"];
I tied but failed. Please help me out
Thanks In Advance :)
var a = "aaaaaabbbbbbbcccccccaa";
function aa(data){
var a = [];
var x = [];
//var b = data.split("")
// var b = data.split("").filter((val,key, arr)=>{
// //console.log(arr.indexOf(val) +" "+ key )
// return arr.indexOf(val) === key
// })
//console.log(b);
for(let i = 0; i<= data.length-1; i++){
for(let j = 0; j<= data.length-1; j++){
if(data[i] !== data[j] && x.indexOf(data[i]+""+j) <0){
x.push(data[i]+""+j);
a.push(data[i] +""+ j);
break;
}
}
}
console.log(x);
return a;
}
console.log(aa(a));
I'd use a regular expression to match repeated characters in the string, then map them to match[0] + match.length to get the concatenated substring for that portion:
const aa = data => data
.match(/(.)\1*/g)
.map(match => match[0] + match.length);
console.log(aa('aaaaaabbbbbbbcccccccaa'));
If you don't want to use a regular expression, don't use a nested loop like that from 0 to the string length - instead, count up repeated characters from inside the first loop, starting at the current i index and incrementing it:
function aa(data) {
const result = [];
for (let i = 0; i < data.length; i++) {
const char = data[i];
let matches = 1;
while (data[i + 1] === char) {
i++;
matches++;
}
result.push(char + matches);
}
return result;
}
console.log(aa('aaaaaabbbbbbbcccccccaa'));

JavaScript: How to count repetitive letters in a string and output the numbers right after?

I am trying to display an output like this a3b2c4d3 for a string aaabbccccddd.
I tried the code below but didn't get the desired result.
var countLetters = "aaabbccccddd";
console.log("countLetters.length --->" + countLetters.length);
var countNumberLetter = 0;
var i;
var a;
for (i = 0; i < countLetters.length; i++) {
if (countLetters[i] == countLetters[i + 1]) {
countNumberLetter = countNumberLetter + 1;
}
}
console.log("countNumberLetter--------->" + countLetters[i] + countNumberLetter);
Use two loops. Use an outer while to loop the string. Whenever a new letter is encountered, use the for loop to increment count as the long as the letters belong to the same sequence. When done increment the outer counter (i) to get to the next letter:
var countLetters = "aaabbccccddd";
var result = '';
var i = 0;
while (i < countLetters.length) {
// iterate until current letter, and counted letter are not equal, increment count
for (var count = 1; countLetters[i] === countLetters[i + count]; count++) {}
// add current letter and count to string
result += countLetters[i] + count;
i += count; // increment outer counter - i
}
console.log(result);
Another solution that uses a String.match() with a regex to get an array of letter sequences. Then maps each sequence to letter + count, and joins them back to a string:
var countLetters = "aaabbccccddd";
var result = countLetters.match(/(\w)\1+/g) // match sequences of the same letter
.map((s) => s[0] + s.length) // map each sequence to letter with count
.join(''); // join back to a string
console.log(result);
var hashMap = {};
var countLetters = "aaabbccccddd";
countLetters.split("").forEach((letter) => {
if(!hashMap[letter]) {
hashMap[letter] = 0;
}
hashMap[letter] = hashMap[letter]+1;
})
var string ='';
for(var i in hashMap) {
var val = hashMap[i];
string += i + val;
}
console.log("countNumberLetter--------->",string);
const object = {};
const string = "aaabbccccddd";
// To iterate over string
for(let i = 0; i < string.length; i++){
// if the object has that alphabet just increment it
if(object.hasOwnProperty(string.charAt(i))){
++object[string.charAt(i)];
}else{
// else create a key to the new alphabet and give it a value 1
object[string.charAt(i)] = 1;
}
}
let finalString = "";
// To iterate over the object
for(let key in object){
finalString += key; // concatenate the key
finalString += object[key]; // concatenate the value
}
console.log(finalString);
My solution has two loops one to iterate over the string and store the alphabet and there count in an object ( you can use hashmap as well ).
The 2nd loop is to iterate over object so that we can make the desired string.

Replace a letter with its alphabet position

This looked fairly straightforward to me when I started, but for some reason I'm getting an empty array everytime I try to run the result on codewars. I'm hoping you can help me identify what the problem is.
function alphabetPosition(text) {
text.split(' ').join('');
var chari = "";
var arr = [];
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for(var i = 0; i < text.len; i++){
chari = text.charAt(i).toLowerCase();
if(alphabet.indexOf(chari) > -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World"));
My idea is to get the text from the parameter then strip out the spaces. I made a variable for my empty array and make an alphabet string that I can later search through. In the for loop, i make each character lowercase, and if the character is found in the alphabet string, its position gets pushed into the array (arr). I appreciate your time.
The Kata works with this code. Try with this one:
function alphabetPosition(text) {
var result = "";
for (var i = 0; i < text.length; i++) {
var code = text.toUpperCase().charCodeAt(i)
if (code > 64 && code < 91) result += (code - 64) + " ";
}
return result.slice(0, result.length - 1);
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
You need the String#length property
text.length
instead of text.len.
function alphabetPosition(text) {
var chari,
arr = [],
alphabet = "abcdefghijklmnopqrstuvwxyz",
i;
for (var i = 0; i < text.length; i++){
chari = text[i].toLowerCase();
if (alphabet.indexOf(chari) !== -1){
arr.push(alphabet.indexOf(chari));
}
}
return arr;
}
console.log(alphabetPosition("Hello World!!1"));
A solution with ES6
function alphabetPosition(text) {
return [...text].map(a => parseInt(a, 36) - 10).filter(a => a >= 0);
}
console.log(alphabetPosition("Hello World!!1"));
First : deleting space
Second : mapping each char with its alphabet rank
Third : test with the string Happy new year
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
var alphabetPosition = text =>
text.split('').map(x => alphabet.indexOf(x) + 1);
console.log(alphabetPosition("happy new year"));
function alphabetPosition(text) {
const words = text.toLowerCase().replace(/[^a-z]/g,"");
return [...words].map(v=> v.charCodeAt() - 96);
}
First we take the text and transform it into lowercase to get rid of the capital letters using text.toLowerCase() and then we do .replace(/[^a-z]/g,"") to replace all the non a-z characters with nothing.
The next step is to spread the string out into an array using [...words] and then mapping it to get the ascii character code of each a-z character.
Since a = 97 and b = 98 etc we will subtract 96 so that we get a = 1 and b = 2 etc (the position of the letters in the alphabet)
You can make it even easier, by making use of the acii code. Because a = ascii code 97, b = 98 etc. And there is a javascript function String.charCodeAt( n ) which returns the ascii code at a specific function. You only have to alter the offset for capitals (if you want to support them).
function alphabetPosition( text ) {
var positions = [];
for ( var i = 0; i < text.length; i++ ) {
var charCode = text.charCodeAt( i );
if ( charCode >= 97 && charCode <= 122 ) {
positions.push( charCode - 96 );
} else if ( charCode >= 65 && charCode <= 90 ) { // get rid of this if you don't care about capitals
positions.push( charCode - 64 );
}
}
return positions;
}
var positions = alphabetPosition( 'Hello World' );
console.log(positions);
Checkout this working fiddle
This example will return based on a 0 based array, and uses lambda expressions with filter. I recycle the original byte array created by splitting the text passed to the method.
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase());
}
return bytes.filter(n => { if(n > -1) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
For a 1 based array result Kata Codewars Friendly
function alphabetPosition(text) {
var bytes = text.split('');
var alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
for (var i = 0, len = text.length; i < len; i++) {
bytes[i] = alphabet.indexOf(bytes[i].toLowerCase()) + 1;
}
return bytes.filter(n => { if(n > 0) return n; } ).join(' ');
}
console.log(alphabetPosition("Hello World"));
You can also use .charCodeAt function:
function alphabetPosition(text) {
start = "a".charCodeAt(0);
end = "z".charCodeAt(0);
res = [];
for (var i = 0; i < text.length; i++) {
index = text.charAt(i).toLowerCase().charCodeAt(0);
if (index >= start && index <= end) {
res.push(index - start +1); // +1 assuming a is 1 instead of 0
} else {
res.push(0); // Or do w/e you like with non-characters
}
}
return res;
}
console.log(alphabetPosition("Hello World"));
You may do something like this;
var alpha = [].reduce.call("abcdefghijklmnopqrstuvwxyz0123456789 .,!",(p,c,i) => (p[c] = i,p),{}),
str = "Happy 2017 whatever..!",
coded = [].map.call(str, c => alpha[c.toLowerCase()]);
console.log(coded);
change len to length:
(var i = 0; i < text.len; i++)
// change to
(var i = 0; i < text.length; i++)
Here is a much shorter version that does the same:
function alphabetPosition(text){
return text.split('').map(function(character){ return character.charCodeAt(0) - 'a'.charCodeAt(0) + 1; })
}
console.log(alphabetPosition("Hello World"));
This was my solution on CodeWars. Works perfectly ;)
let alphabetPosition = (text) => {
let str = Array.from(text.toLowerCase().replace(/[^a-z]/g,''));
let arr = [];
for (let i = 0; i < str.length; i++) {
arr.push(str[i].charCodeAt() - 96);
}
return arr.join(' ');
}
my answer
function alphabetPosition(text) {
if (text.match(/[a-z]/gi)) { // if text is not emtpty
let justAlphabet = text.match(/[a-z]/gi).join("").toLowerCase(); //first extract characters other than letters
let alphabet = "abcdefghijklmnopqrstuvwxyz";
let a = []; // Create an empty array
for (let i = 0; i < justAlphabet.length; i++) {
a.push(alphabet.indexOf(justAlphabet[i]) + 1); //and characters index number push in this array
}
return a.join(" ");
} else {
return "";
}
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
this one should work
const lineNumberHandler = (arr) => {
const alphabet = 'abcdefghijklmnopqrstuwxyz';
return arr.map((el) => `${alphabet.indexOf(el) + 1}:${el}`);
}
This may solve the issue too:
function alphabetPosition(text) {
const alphabet = 'abcdefghijklmnopqrstuvwxyz'
const textWithoutSpaces = text.replace(/\s/g, '');
const numbers = Array.from(textWithoutSpaces).map((letter) => {
const lowerCaseLetter = letter.toLowerCase();
const charI = alphabet.indexOf(lowerCaseLetter)+1
if(charI) return charI
return null
})
const withoutEmptyValues = numbers.filter(Boolean)
return withoutEmptyValues.join(' ')
}
function alphabetPosition(text) {
const letters = text.split('')
const result = letters.map((l, ix) => {
const code = l.toUpperCase().charCodeAt() - 64
if (l.length && code > 0 && code <= 26) {
return code
}
})
return result.join(' ').replace(/\s+/g, ' ').trim()
}
I like to do "Single Line Responsibility", so in every line you can find only one action.
The return line, delete all multiples spaces.
An optimized version of it.
function alphabetPosition(text) {
let split = text.split("");
split = split.filter((el) => /^[a-zA-Z]+$/.test(el));
let str = "";
split.forEach(
(el) => (str += el.toLowerCase().charCodeAt(0) - "96" + " ")
);
return str.trim();
}
console.log(alphabetPosition("The sunset sets at twelve o' clock."));
function alphaPosition(test){
//the object assigns the position value to every alphabet property
const lookupAlph = {a:1,b:2,c:3,d:4,e:5,f:6,g:7,h:8,i:9,j:10,k:11,l:12,m:13,n:14,o:15,p:16,q:17,r:18,s:19,t:20,u:21,v:22,w:23,x:24,y:25,z:26}
//converts our text first to lowercase, then removes every non-alphabet
// it proceeds to covert the text to an array,
// then we use the map method to convert it to its position in the alphabet
// the last thing we do is convert our array back to a string using the join method
const alphaPosition = text.toLowerCase()
.replace(/[^a-z]/g, "")
.split("")
.map((a) => lookupAlph[a])
.join(" ")
return alphaPosition;
}

Categories