I am creating a cipher that takes a string and changes each letter to move forward 3 spaces. For instance "Hello!" would turn into "Khoor!", but I have hit a snag. When people type in something that isn't a letter, like a "!" or a space in between letters, I want to be able to just return that value. So a "!" would stay a "!" and a space would stay a space. I want to create an if statement inside of a loop to accomplish this, but how do I differentiate between letters and non-letters?
Attached is my loop, and I want to be able to put in an if statement so it would read "if input is non-letter, then return input. If input is a letter then move forward 3 spaces."
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 string = "Hello World!"
var stringArr = string.split("")
var codedLet = [];
for (var i = 0; i < string.length; i++) {
var input = stringArr[i].toLowerCase()
var codedNum = alphabet.indexOf(input) + 3
codedLet[i] = alphabet[codedNum]
}
There are two ways :
One would be to use regex of the type [a-zA-Z]{1} or you can try something like
if(c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
If you need a cipher which shifts symbols, why not to shift all of them?
See the snippet below:
let string = "Hello World!"
const cipher = (s) => [...s].reduce(
(a, l) => a + String.fromCodePoint(l.codePointAt() + 3), '')
const decipher = (s) => [...s].reduce(
(a, l) => a + String.fromCodePoint(l.codePointAt() - 3), '')
let cs = cipher(string)
console.log(cs)
console.log(decipher(cs))
Related
I have this piece of code that adds some gaps into a word/phrase like this:
"I drove everywhere by car" > "I d_o_e e_e_y_h_r_ _y c_r_"
How can it be transformed so it would to a result that is a little different:
"I drove everywhere by car" > "I d___e e___y___r_ b_ c__"
The difference is that it would show the first letter of every word, then make a 3-letter gap, and, if the word is long enough, show the 5th letter, another 3-letter gap and so on.
The piece of code:
var str = document.getElementById("dropped-v").innerHTML;
letters = '';
for (var i = 0, len = str.length; i < len; i++) {
if (i % 2 != 0 && str[i] != ' ') {
letters += '<span class="hint">_</span>';
}
else {
letters += str[i];
}
}
document.getElementById("dropped-v").innerHTML = letters;
Here's one way to do it for simple sentences without periods. You can add period support and HTML injection as needed.
let MASK = '_';
function obfuscate_word(word) {
const letters = [...word];
const mask_letters = letters.map((letter, i) => i % 4 == 0 ? letter : MASK);
return mask_letters.join('');
}
function obfuscate_sentence(sentence) {
const words = sentence.split(' ');
const mask_words = words.map(word => obfuscate_word(word));
return mask_words.join(' ');
}
const s = "I drove everywhere by car"
console.log(s);
console.log(obfuscate_sentence(s));
If you want to, you can replace the MASK and get/set your HTML something like this:
MASK = '<span class="hint">_</span>';
const e = document.getElementById("dropped-v");
e.innerHTML = obfuscate_sentence(e.innerHTML);
This assumes that the inner HTML of the dropped-v element is a simple sentence (and not a previously-obfuscated sentence that includes markup, for example).
Example
฿33.00 => ฿3X.XX
฿111.00 => ฿1XX.XX
฿33,333.00 => ฿3X,XXX.XX
How to replace money "xxx" By Javascript Or jQuery
You could use something like that :
var input="฿33.00";
if (input.length > 2 && input[0] == "฿" && !isNaN(input[1])) {
var output = input.substring(0,2);
for (var i=2; i<input.length; i++) {
output += isNaN(input[i]) ? input[i] : "X";
}
console.log(output);
}
In this code we first check that the transformation is applicable (input has at least 3 characters, first char is the currency symbol, second is a digit), then we create a string that starts with the first two characters of the input and which we continue by iterating over the input, adding an "X" to the output if it's a digit and the character (a dot or comma assumedly) otherwise.
Using a regex, map and replace
const lines = `฿33.00
฿111.00
฿33,333.00`.split(/\s+/)
const res = lines.map(line => {
let [a, b, c] = line.match(/(฿\d)(.*)/); // capture the ฿+first digit plus rest
return b + c.replace(/[0-9]/g, "X"); // replace the numbers in the rest
});
console.log(res)
Let's say I have this string: "a_b_c_d_restofthestring" and I only want to keep (e.g.) 2 underscores. So,
"a_b_cdrestofthestring"
"abc_d_restofthestring"
Are both valid outputs.
My current implementation is:
let str = "___sdaj___osad$%^&*";
document.getElementById('input').innerText = str;
let u = 0;
str = str.split("").reduce((output, c) => {
if (c == "_") u++;
return u < 2 || c != "_" ? output + c : output;
});
document.getElementById('output').innerText = str;
<div id="input"></div>
<div id="output"></div>
But I'd like to know if there's a better way...
Your code seems to work fine, but here's a one-liner regular expression that replaces all but the last two underscores from the input string.
let input = "___sdaj___osad$%^&*";
let output = input.replace(/_(?=(.*_){2})/g, '');
console.log("input: " + input);
console.log("output: " + output);
This of course is not very generalized, and you'd have to modify the regular expression every time you wanted to say, replace a character other than underscore, or allow 3 occurrences. But if you're okay with that, then this solution has a bit less code to maintain.
Update: Here's an alternate version, that's fully generic and should perform a bit better:
let input = "___sdaj___osad$%^&*";
function replace(input, char = '_', max = 2, replaceWith = '') {
let result = "";
const len = input.length;
for (let i = 0, u = 0; i < len; i++) {
let c = input[i];
result += (c === char && ++u > max) ? replaceWith : c;
}
return result;
}
console.log("input: ", input);
console.log("output: ", replace(input));
See this jsPerf analysis.
You could take a regular expression which looks for an underscore and a counter of the keeping underscores and replace all others.
var string = "a_b_c_d_restofthestring",
result = string.replace(/_/g, (c => _ => c && c-- ? _ : '')(2));
console.log(result);
I want to write this google spreadsheet javascript code to replace random letters in a string.
I have created a code that does it but not randomly, plus it also replaces the spaces with an underscore (which is problematic).
The end result I'm interested in is to go from this (the sentences are in French btw.):
'J’habite à New York.'
to this:
'_’h_b_t_ à _ew _or_.'
Let's say that given a sentences, at least half of the number of letters must be replaced with an underscore.
Thank you for your help. (ps: i'm not a programmer)
The code I have so far:
var v = [['J’habite à New York.', 'Sì', ], ['Je m’appelle John. !']];
for (var r in v){
for (var c in v[r]){
var d = v[r][c];
var l = d.length;
var u = l;
while(u > 0){
var res = d.replace(d[u-2], '_');
d = res;
u = u - 2;
}
console.log(res);
}
}
You might try something like this :)
var a = "Text i want to replace text from";
var splitted = a.split('');
var count = 0; // variable where i keep trace of how many _ i have inserted
while(count < a.length/2) {
var index = Math.floor(Math.random()*a.length); //generate new index
if(splitted[index] !== '_' && splitted[index] !== ' ') {
splitted[index] = '_';
count++;
}
}
var newstring = splitted.join(""); //the new string with spaces replaced
EDIT: i tried it now on console and seems to be working. What problem does it give to you?
2° EDIT: you could do:
splitted[index] = ' _ ';
instead of
splitted[index] = '_';
also notice that i changed the if condition from:
if(splitted[index] !== '_')
to
if(splitted[index] !== '_' && splitted[index] !== ' ')
to avoid replacing empty spaces with '_'
:)
You are overcomplicatig a bit. Just turn the string into an array of characters, then map it to an array of characters with some letters replaced and turn it back into a string.
function replace(str) {
return str.split("").map(char => Math.random() > 0.5 ? "_" : char).join("");
}
var v = [
['J’habite à New York.', 'Sì', ],
['Je m’appelle John. !', 'Non!',]
];
for (const pair of v) {
pair[0] = replace(pair[0]);
pair[1] = replace(pair[1]);
}
console.log(v)
What the challenge asks:
Using the JavaScript language, have the function LetterChanges(str) take the str parameter being passed and modify it using the following algorithm. Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a). Then capitalize every vowel in this new string (a, e, i, o, u) and finally return this modified string.
My solution:
function LetterChanges(str) {
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 vowels = [a,e,i,o,u];
var stringToArray = str.split("");
for (i=0; i<=stringToArray.length; i++){ //goes through new array one-by-one
var originalLetter = stringToArray[i] // names each letter
var alphabetPosition = alphabet.indexOf(); // finds letter position in alphabet array
var newAlphabetPosition = alphabetPosition + 1; // adds one to that position
var newLetter = alphabet[newAlphabetPosition]; // changes the old letter to the new
newLetter = stringToArray[i]; // sends new letter to its position on new array
if (newLetter.isInArray(vowels){ // finds if new letter is a vowel
newLetter = newLetter.toUpperCase(); // if yes, turn into upper case
}
str = stringToArray.toStr() //turns array back to string, and names it str
}
return str;
}
I've tried to be very clear on my thinking, adding the steps one by one. Please refrain from using quick methods, since I really want to correctly understand the reasoning behind the challenge, and not memorize methods.
The code doesn't work... because of a few errors:
What is i? Did you forget to declare it?
Once you convert a string to an array... the first character starts at 0, and the last character is length -1. Your for-loop conditional has i <= stringToArray.length which would include one character beyond the array length.
var alphabetPosition = alphabet.indexOf(); Index of what? Did you forget indexOf(originalLetter)?
You forgot "z". You need some logic to "wrap-around" back to "a".
isInArray isNotAFunctionYouShowedUs. Actually Javascript only has "indexOf" which returns -1 on no-match... unless I'm mistaken.
function LetterChanges(str) {
for (var i = 0; i < str.length; i++) {
var newCharCode = str.charCodeAt(i) + 1; //Get Decimal Value for character at index "i", and increment by 1.
if (newCharCode == 123) { //Pesky 'z' becomes '{'. Lets change it to 'a' instead.
newCharCode = 97; // 'a' = 97.
}
if ([97,101,105,111,117].indexOf(newCharCode)!=-1) { //Is it a vowel? (97 = a, 101 = e, 105 = i, 111= o, 117 = u)
newCharCode-=32; //Make it capital. (65 = A, 69 = E, 73 = I, 79 = O, 85 = U)
}
console.log(newCharCode);
str = str.substr(0,i) + String.fromCharCode(newCharCode) + str.substr(i+1); //Convert it back to a character, and stick it back into the string.
console.log(str);
}
return str;
}
I marked up something kinda quick... just for fun. (untested) It only makes use of 2 variables and does some old fashioned ascii trickery.
My CoderByte Solutions (https://github.com/ambatiramireddy/My-CoderByte-Solutions)
function LetterChanges(str) {
var vowels = 'aeiou', result = '', changedChar;
for (i = 0; i < str.length; i++) {
var c = str.charCodeAt(i);
if (c >= 97 && c < 122)
changedChar = String.fromCharCode(c + 1);
else if (c == 122)
changedChar = String.fromCharCode(97);
else
changedChar = str[i];
if (vowels.indexOf(changedChar) != -1)
changedChar = changedChar.toUpperCase();
result += changedChar;
}
return result;
}