I am working on a Codewars problem and have been able to solve the majority of this problem except the final part. The challenge is "rot13"
ROT13 is a simple letter substitution cipher that replaces a letter with the letter 13 letters after it in the alphabet. ROT13 is an example of the Caesar cipher. Create a function that takes a string and returns the string ciphered with Rot13.
function rot13(message){
message = message.split('');
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'];
let indexes = message.map(char => alphabet.indexOf(char));
let result = indexes.map(i => {
let val = i + 13;
let max = 26;
if (val > max) {
let temp = val - max;
val = temp;
}
return val;
});
//result = [6, 17, 5, 6];
//i want to use the elements in my result array, and
//grab the letters from my alphabet array whose indexes associate with those elements from my result array
}
rot13('test') // 'grfg'
This is my current state in this problem. I have tried checking if any of the indexes of the elements in alphabet === the elements in my result array and if so, pushing those characters from the my alphabet array into an empty array but I am receiving -1
Any suggestions for approaching this problem/altering my thought process will be helpful. Thanks!
To answer your question directly, you can just add:
return results.map(i => alphabet[i]).join('')
at the end of the function.
As a side note, instead of having an array of letters you can utilize the String.fromCharCode function. It translates a number into ASCII char equivalent (capital letters start at 65).
function rot13(message){
message = message.split('');
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'];
let indexes = message.map(char => alphabet.indexOf(char));
let result = indexes.map(i => {
let val = i + 13;
let max = 26;
if (val > max) {
let temp = val - max;
val = temp;
}
return val;
});
return result.map(i => alphabet[i]).join('');
}
console.log(rot13('test')) // 'grfg'
Use another map() to convert result back to characters by indexing alphabet. Then use join('') to make it a string. Then return it to the caller.
You can simplify the ROT13 calculation using modulus.
function rot13(message) {
message = message.split('');
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'];
let indexes = message.map(char => alphabet.indexOf(char));
let result = indexes.map(i => {
let val = (i + 13) % 26;
return val;
});
return result.map(i => alphabet[i]).join('');
}
console.log(rot13('test'));
Note that this will only work correctly if the string only contains lowercase letters. Anything else will return -1 from indexOf, and you'll need to check for that.
Try this
function rot13(message) {
message = message.split('');
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'];
return message.map(char => {
let i = alphabet.indexOf(char);
i = (i + 13) % alphabet.length;
return alphabet[i];
}).join("");
}
console.log(rot13('test')); // 'grfg'
Try this:
function rot13(message){
message = message.split('');
let finalResult = "";
const 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'];
message.forEach(item => {
const index = alphabet.indexOf(item);
let cipherIndex = index + 13;
if(cipherIndex > 25)
cipherIndex = index - 13
finalResult = finalResult + alphabet[cipherIndex]
})
return finalResult;
}
Related
This question already has answers here:
Split array into chunks
(73 answers)
Closed 5 months ago.
Like if there are 20 elements in an array what is the quickest way to filter them out by tens?
Like for example elements, 0-9 and then 10-21?
I think, what you mean is splitting the array to chunks each chunk with size equal to ten.
function chunkArray(array, size) {
let result = []
for (let i = 0; i < array.length; i += size) {
let chunk = array.slice(i, i + size)
result.push(chunk)
}
return result
}
let arr = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't'];
let arrPairs = chunkArray(arr, 10);
console.log(arrPairs);
You can try:
array.reduce((accum, current) => {
if (accum[accum.length - 1].length === 10) {
accum.push([]);
}
accum[accum.length - 1].push(current);
return accum;
},[[]])
♦ pattern:
e,b,c,d,i,f,g,h,o,j,k,l,m,n,u,p,q,r,s,t,a,v,w,x,y,z
I want to sort my words from arr alphabetically by 1st letter and then by 2nd letter of a similar word matched by 1st letter according to my given pattern.
['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd']
♦ output should be:
['aibcdh', 'aobcdh', 'aabcdh', 'aacbdh', 'cighjd', 'cfghjd' ]
♦ or:
aibcdh
aobcdh
aabcdh
aacbdh
cighjd
cfghjd
My Code here:
let pattern = ['e', 'b', 'c', 'd', 'i', 'f', 'g', 'h', 'o', 'j', 'k', 'l', 'm', 'n', 'u', 'p', 'q', 'r', 's', 't', 'a', 'v', 'w', 'x', 'y', 'z']
let arr = ['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd']
let arrSorted = arr.sort() //Natural sorting
console.log(arrSorted)
// output in array
const newArr = arrSorted.sort((a, b) => pattern.indexOf(a[1]) - pattern.indexOf(b[1]))
console.log(newArr) //Sorted by its 2nd character with given pattern
// single output without array
for (let i = 0; i < pattern.length; i++) {
for (let j = 0; j < arrSorted.length; j++) {
if (pattern[i] === arrSorted[j][1]) {
console.log(arrSorted[j]) //Sorted by its 2nd character with given pattern
}
}
}
You could sort the first by string and the second by custom value.
const
pattern = 'ebcdifghojklmnupqrstavwxyz',
array = ['aobcdh', 'aibcdh', 'aabcdh', 'aacbdh', 'cfghjd', 'cighjd'],
order = Object.fromEntries(Array.from(pattern, (l, i) => [l, i + 1]));
array.sort((a, b) =>
a[0].localeCompare(b[0]) ||
order[a[1]] - order[b[1]]
);
console.log(array);
I want to get the exact difference between two string arrays.
const array1 = ['T','E','A','P','A','P','E','R'];
const array2 = ['T','A','P'];
Expected Output Array:
['E','A','P','E','R']
I have tried this method:
const output = array1.filter(char => array2.includes(char));
But that removes all instances of a character, like:
['E','E','R']
I'm a newbie, so could you guide me to the right direction?
You could take a closure over the index for the second array and increment the index and remove this item from the result set.
var array1 = ['T', 'E', 'A', 'P', 'A', 'P', 'E', 'R'],
array2 = ['T', 'A', 'P'],
result = array1.filter((i => v => array2[i] !== v || !++i)(0));
console.log(result);
A different approach without a predefined order of array2.
var array1 = ['T', 'E', 'A', 'P', 'A', 'P', 'E', 'R'],
array2 = ['T', 'A', 'P'],
set2 = new Set(array2)
result = array1.filter(v => !set2.delete(v));
console.log(result);
You could remove elements from allowed based on the input array:
const allowed = ['T','E','A','P','A','P','E','R'];
const input = ['T','A','P'];
for(const char of input) {
const pos = allowed.indexOf(char);
if(pos === -1) {
// char doesnt exist?
} else {
allowed.splice(pos, 1);
}
}
Then allowed will be your expected result at the end.
I think filter is not correct apparoch here. Because there are some elements repeadted. Use a simple for-loop. And remove the elements when you add it to result.
const array1 = ['T','E','A','P','A','P','E','R'];
const array2 = ['T','A','P'];
const copy = [...array2];
let res = [];
for(let i = 0;i<array1.length;i++){
let index = copy.indexOf(array1[i]);
if(index === -1){
res.push(array1[i]);
}
else copy.splice(index,1);
}
console.log(res)
I have an array of the entire alphabet from a to z. I also have an input field. I want to be able to find the index of each character from the input field in the alphabet array but my function doesn't work. I've tried storing the text from the input field into an array, and I've tried using a named function for it as well but neither worked.
<input type="text" id="plaintext" placeholder="Plaintext">
<div id="start"><div id="start_text">Start</div></div>
let plaintext = document.getElementById("plaintext");
let alph = ['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'];
let startB = document.getElementById("start");
let plainParser = [];
startB.addEventListener('click', () => {
for(let i=0; i < alph.length; i++){
console.log(alph.findIndex( () => plainParser.push(plaintext.value.split(''))));
};
});
A shortcut without needing the array is use the charCode of each character.
a starts at 97
const str = 'abc';
for(let s of str){
console.log(s.charCodeAt(0) - 97);
}
I want to … find the index of each character from the input field in the alphabet array
Then instead of looping from 0 to 25:
for(let i=0; i < alph.length; i++){
you should loop over every character from the input:
for (let c of plaintext.value) {
I want to … find the index of each character from the input field in the alphabet array
You have the character, so find the index:
alph.indexOf(c)
v‘là.
let plaintext = document.getElementById("plaintext");
let alph = ['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'];
let startB = document.getElementById("start");
startB.addEventListener('click', () => {
for (let c of plaintext.value) {
console.log(alph.indexOf(c));
}
});
Here's a slightly refactored version of what I think you are looking for:
const alphabet = 'abcdefghijklmnopqrstuvwxyz';
const result = document.querySelector(".result");
const plaintext = document.getElementById("plaintext");
const startB = document.querySelector(".start");
startB.addEventListener('click', () => {
const source = plaintext.value;
result.innerText = '';
if (!source) return;
const indices = [];
for (let char of source) {
indices.push(alphabet.indexOf(char));
}
result.innerText = indices.join(', ');
});
<input type="text" id="plaintext" placeholder="Plaintext">
<button class="start">Start</button>
<div class="result" style="font-family: monospace;"></div>
I'm trying to build a simple "cipher" to assign the letters in a string the value of a reversed alphabet (e.g. a=z b=y, etc..) I built a for statement that seems to work until the last call and instead of giving the reversed value instead gives the original value.
I commented out each line in the for statement and then worked through them one at a time to check their returns. The second to last statement (c = rev.indexOf(c);) give the value of 25, 24, 23 (as expected) so I don't understand why when it looks them up in the "letters" matrix it gives a return of a, b, c instead of z, y, x.
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'x', 'z'];
var rev = letters.reverse();
var stringy = function(n){
ns = n.split("");
for (i = 0; i < n.length; i++){
c = ns[i];
c = rev.indexOf(c);
c = letters[c];
console.log(c);
}
}
stringy("abc");
letters.reverse() doesn't just return the reversed array. It reverses the array in place.
If you check the contents of letters after letters.reverse() you'll see that the order has been reversed.
You can use .slice() to make a copy of the array, which you can then reverse:
var rev = letters.slice().reverse();
As an addition to zzzzBov information to the Array.reverse() method, I thought I would add an answer that doesn't require reversing your letters. There is no need to keep 2 variables just to reverse them based on the index, just find the index in the letters array and search from the end of the letters array back.
I added a slightly modified version of your code, to show how you could make it yourself a bit easier and added some code comments where I thought appropriate
// make your debugging easier
'use strict';
var letters = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'y', 'x', 'z'];
var getReversedCypher = function( text, sequence, unmatched ) {
if (!text) {
return '';
}
var ns = text.split(''),
cypher = [],
lastLetterIndex = sequence.length - 1;
// use strict adds forEach on arrays
ns.forEach(function(char) {
var index = sequence.indexOf(char);
if (index < 0) {
// couldn't find a match, you could throw an error, I chose to add an extra character
cypher.push( unmatched || '-' );
} else {
// no need to use a reversed lookup, just search the table from the end
cypher.push( sequence[lastLetterIndex-index] );
}
});
return cypher.join('');
};
// make some utility methods to still use your simple function
var encode = function( text ) {
return getReversedCypher( text, letters, '-' );
};
var decode = function( text ) {
return getReversedCypher( text, [].concat(letters).reverse(), ' ' );
};
var encoded = encode("this is the sound of speech"), decoded = decode(encoded);
console.log('cypher: ' + encoded);
console.log('decoded: ' + decoded);