I'm trying to do a caesar cipher in javascript, I'm very new at this. I know i have to limit the ascii so that it's only letters. Because like this if we insert the letter "z" and the key "3" it won't give us "c", but something else. I've tried to search but i can't seem to understand how to do that. Thanks in advance for any help.
var letter=readLine("letter?");
var key=parseInt(readLine("key?"));
var result= letter.charCodeAt(0)+key;
print(String.fromCharCode(result));
If I understand correctly, it should work:
for(var i =0; i<letter.length;i++){
print(String.fromCharCode(letter.charCodeAt(i) + key))
}
I know this is an outdated question but since no one has posted the answer:
To shift only letters you can use this:
caesarCipher = (s, k) => {
let string = s;
string = string.replace(/[a-z]/g, str => String.fromCharCode((str.charCodeAt(0) - 97 + k) % 26 + 97));
string = string.replace(/[A-Z]/g, str => String.fromCharCode((str.charCodeAt(0) - 65 + k) % 26 + 65));
return string;
}
Related
I am wondering about runtimes for replacing a character in a string (in javascript).
For example
let str = "hello world";
str[0] = "n";
console.log(str); // hello world
under strict mode, this throws an error because you cannot modify strings (read only).
How would you implement an O(1) time, O(1) space algorithm in js to do str[index] = char? In C, this is trivial because access is O(1) and you can modify that element without having to allocate a new array and copy values over.
I have found solutions using split to do this ... but isnt this overkill? That means O(n) time and space.
Wondering about this mostly for interview questions since I use javascript
You can use the .replace("","") function.
Ex:
let str = "hello world";
str = str.replace("hello", "this");
console.log(str); // this world
Example codepen:https://codepen.io/darrow8/pen/VNjyJP
More info: https://www.w3schools.com/jsref/jsref_replace.asp
You can use substring:
"use strict";
const replaceCharAt = (s, c, i) => i ? (i != 1 ? c + s.substring(i + 1) : s[0] + c + s.substring(3)) : c + s.substring(i);
let str = "hello world";
str = replaceCharAt(str, "n", 0);
str = replaceCharAt(str, "3", 1);
console.log(str);
In JavaScript, strings are immutable, so the best you can do is create a new string with the changes you need (so, forget about O(1)), the best I can think now is using the replacement function of string.replace():
const replaceAt = (str, idx, char) =>
{
return str.replace(/./g, (match, offset) => offset === idx ? char : match);
}
console.log(replaceAt("Hello", 1, "3"));
Or, with String.slice():
const replaceAt = (str, idx, char) =>
{
return str.slice(0, idx) + char + str.slice(idx + 1);
}
console.log(replaceAt("Hello", 1, "3"));
I have some problems with replacing every 6th colon in my array. Have tried something with Regex, but that doesn't seem to work. I have red other questions were people are using nth and then set this variabele to the index you want to replace, but can't figure out why that isn't working. I used the join function to replace the ',' in my array with ':'.
arrayProducts[i] = arrayProducts[i].join(':');
When i use console.log(arrayProducts); this is my result:
F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3
This is what I want:
F200:0:0.0000:1:100:0:1,KPO2:0:0.0000:1:200:0:2,HGB1:0:0.0000:1:300:0:3
Thanks for reading!
Edit: F200, KP02 and HGB1, could also be numbers / digits like: 210, 89, 102 so the :[A-Z] method from regex doesn't work.
You can just count the number of colon occurences and replace every nth of them.
var str = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3', counter = 0;
res = str.replace(/:/g, function(v) {
counter++;
return !(counter % 7) ? ',' : v;
});
console.log(res);
A regex solution is viable. You can use a function as the second parameter of the .replace method to make full use of backreferences.
var str = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3';
str = str.replace(/((?:[^:]*:){6}(?:[^:]*)):/g, function() {
var matches = arguments;
return matches[1] + ',';
});
console.log(str);
What you are looking for is to split over the following expression :[A-Z]
(assuming that your rows always start with this range)
a simple solution could be:
mystring.split(/:[A-Z]/).join(',')
/:[A-Z]/ matches any : followed by a uppercase letter
You could use replace with a look for six parts with colon and replace the seventh.
var string = 'F200:0:0.0000:1:100:0:1:KPO2:0:0.0000:1:200:0:2:HGB1:0:0.0000:1:300:0:3',
result = string.replace(/(([^:]*:){6}[^:]*):/g, '$1,');
console.log(result);
Another solution (based on the number of iteration)
using map method:
str.split(':').map((v, i) => (i % 7 === 0 ? ',' : ':') + v ).join('').slice(1)
using reduce method:
str.split(':').reduce((acc,v, i) => {
return acc + (i % 7 === 0 ? ',' : ':' ) + v ;
}, '').slice(1)
Note: arrow expression does not work on old browsers
maybe you can try this approach,
loop your array and join it manually, something like :
var strarr = "F200:0:00000:1:100:0:1:KPO2:0:00000:1:200:0:2:HGB1:0:00000:1:300:0:3";
var arr = strarr.split(":")
var resStr = "";
for(var i = 0; i < arr.length; i++)
{
if(i > 0 && i%7 == 0)
resStr = resStr + "," + arr[i]
else
resStr = resStr + ( resStr == "" ? "" : ":") + arr[i];
}
console.log(resStr);
I have a string, var str = "Runner, The (1999)";
Using substr(), I need to see if ", The" is contained in str starting from 7 characters back, then if it is, remove those characters and put them in the start. Something like this:
if (str.substr(-7) === ', The') // If str has ', The' starting from 7 characters back...
{
str = 'The ' + str.substr(-7, 5); // Add 'The ' to the start of str and remove it from middle.
}
The resulting str should equal "The Runner (1999)"
Please, no regular expressions or other functions. I'm trying to learn how to use substr.
Here you go, using only substr as requested:
var str = "Runner, The (1999)";
if(str.substr(-12, 5) === ', The') {
str = 'The ' + str.substr(0, str.length - 12) + str.substr(-7);
}
alert(str);
Working JSFiddle
It should be noted that this is not the best way to achieve what you want (especially using hardcoded values like -7 – almost never as good as using things like lastIndexOf, regex, etc). But you wanted substr, so there it is.
var str = "Runner, The (1999)";
if(str.indexOf(", The") != -1) {
str = "The "+str.replace(", The","");
}
If you want to use just substr:
var a = "Runner, The (1999)"
var newStr;
if (str.substr(-7) === ', The')
newStr= 'The ' +a.substr(0,a.length-a.indexOf('The')-4) + a.substr(a.indexOf('The')+3)
Use a.substr(0,a.length-a.indexOf('The')-4) to obtain the words before "The" and a.substr(a.indexOf('The')+3) to obtain the words after it.
So, you say that the solution should be limited to only substr method.
There will be different solutions depending on what you mean by:
", The" is contained in str starting from 7 characters back
If you mean that it's found exactly in -7 position, then the code could look like this (I replaced -7 with -12, so that the code returned true):
function one() {
var a = "Runner, The (1999)";
var b = ", The";
var c = a.substr(-12, b.length);
if (c == b) {
a = "The " + a.substr(0, a.length - 12) +
a.substr(a.length - 12 + b.length);
}
}
If, however, substring ", The" can be found anywhere between position -7 and the end of the string, and you really need to use only substr, then check this out:
function two() {
var a = "Runner, The (1999)";
var b = ", The";
for (var i = a.length - 12; i < a.length - b.length; i++) {
if (a.substr(i, b.length) == b) {
a = "The " + a.substr(0, i) + a.substr(i + b.length);
break;
}
}
}
I'm having trouble with Coderbyte's challenge
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.
Here's my code:
function LetterChanges(str) {
str = str.toLowerCase();
var al = "abcdefghijklmnopqrstuvwxyz";
var vo = "aeiou";
var newStr = "";
for (var i = 0;i < str.length;i++) {
if (al.charAt(al.indexOf(str.charAt(i))) == "z") {
newStr += "A";
}
else if (str.charAt(i) == " "){
newStr += " ";
}
else {
if (al.charAt(al.indexOf(str.charAt(i))+1) == vo.charAt(vo.indexOf(str.charAt(i)))) {
newStr += vo.charAt(vo.indexOf(str.charAt(i))+1).toUpperCase();
}
else {
newStr += al.charAt(al.indexOf(str.charAt(i))+1)
}
}
}
console.log(newStr);
}
LetterChanges("Argument goes here")
This is returning the following into the console:
bshvnfou hpft ifsf
but what I need to be returned is:
bshvnfOU hpft Ifsf
I can't figure out why my .toUpperCase() isn't working. Any help that you can provide is very much appreciated!
Your problem isn't that toUpperCase() isn't working, it's that your code never gets to that point.
Your
if (al.charAt(al.indexOf(str.charAt(i))+1) == vo.charAt(vo.indexOf(str.charAt(i))))
never passes, because of that +1. There's no need for that there, and if you remove it, uppercase vowels will appear. There are other problems with your code beyond that point, but I'll let you solve them as part of the challenge :-)
Wow, it's crazy looking at the code I wrote a year ago! Reviewing this question, here's what I came up with (disclaimer: still getting comfortable with ES6):
function convertText (str) {
const al = 'abcdefghijklmnopqrstuvwxyz';
return str.toLowerCase().split('').map(letter => {
if (letter.match(/\W/)) return letter;
const index = al.indexOf(letter),
newLetter = (al[index + 1] || al[0]);
return newLetter.match(/[aeiou]/) ? newLetter.toUpperCase() : newLetter;
}).join('');
}
And by using character codes:
function letterChanges (str) {
const v = {d: 69, h: 73, n: 79, t: 85, z: 65};
return str.toLowerCase().split('').map(l =>
(l.match(/\W/) ? l : String.fromCharCode(v[l] || l.charCodeAt(0) + 1))
).join('');
}
There're probably better ways, but still a fun question! Thanks again for your help, #MattDiamant
Here's my solution. It does not satisfy the z becomes a requirement but it passes Coderbyte's test as seen in the screenshot below.
function LetterChanges(str) {
return str
.replace(/[a-z]/gi, c => String.fromCharCode(c.charCodeAt(0) + 1))
.replace(/[aeiou]/gi, c => c.toUpperCase());
}
// keep this function call here
LetterChanges(readline());
Letter Changes Javascript Solution
To account for the non-[a-z] characters can toss this in the if statement and it will account for white space and [^a-z]:
if (letter.match(/[^a-z]/)) return letter;
I want to create a string in JavaScript that contains all ascii characters. How can I do this?
var s = ' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
My javascript is a bit rusty, but something like this:
s = '';
for( var i = 32; i <= 126; i++ )
{
s += String.fromCharCode( i );
}
Not sure if the range is correct though.
Edit:
Seems it should be 32 to 127 then. Adjusted.
Edit 2:
Since char 127 isn't a printable character either, we'll have to narrow it down to 32 <= c <= 126, in stead of 32 <= c <= 127.
Just loop the character codes and convert each to a character:
var s = '';
for (var i=32; i<=127;i++) s += String.fromCharCode(i);
Just wanted to put this here for reference. (takes about 13/100 to 26/100 of a ms on my computer to generate).
var allAsciiPrintables = JSON.stringify((Array.from(Array(126 + 32).keys()).slice(32).map((item) => {
return String.fromCharCode(item);
})).join(''));
Decomposed:
var allAsciiPrintables = (function() {
/* ArrayIterator */
var result = Array(126 + 32).keys();
/* [0, 126 + 32] */
result = Array.from(result);
/* [32, 126 + 32] */
result = result.slice(32);
/* transform each item from Number to its ASCII as String. */
result = result.map((item) => {
return String.fromCharCode(item);
});
/* convert from array of each string[1] to a single string */
result = result.join('');
/* create an escaped string so you can replace this code with the string
to avoid having to calculate this on each time the program runs */
result = JSON.stringify(result);
/* return the string */
return result;
})();
The most efficient solution(if you do want to generate the whole set each time the script runs, is probably)(takes around 3/100-35/100 of a millisecond on my computer to generate).
var allAsciiPrintables = (() => {
var result = new Array(126-32);
for (var i = 32; i <= 126; ++i) {
result[i - 32] = (String.fromCharCode(i));
}
return JSON.stringify(result.join(''));
})();
strangely, this is only 3-10 times slower than assigning the string literal directly(with backticks to tell javascript to avoid most backslash parsing).
var x;
var t;
t = performance.now();
x = '!\"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
t = performance.now() - t;
console.log(t);
.
This is a version written in python. Gives all ASCII characters in order as a single string.
all_ascii = ''.join(chr(k) for k in range(128)) # 7 bits
all_chars = ''.join(chr(k) for k in range(256)) # 8 bits
printable_ascii = ''.join(chr(k) for k in range(128) if len(repr(chr(k))) == 3)
>>> print(printable_ascii)
' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~'
The last string here, printable_ascii contains only those characters that contain no escapes (i.e. have length == 1). The chars like: \x05, \x06 or \t, \n which does not have its own glyph in your system's font, are filtered out.
len(repr(chr(k))) == 3 includes 2 quotes that come from repr call.
Without doing several appends:
var s = Array.apply(null, Array(127-32))
.map(function(x,i) {
return String.fromCharCode(i+32);
}).join("");
document.write(s);
Here is an ES6 one liner:
asciiChars = Array.from({ length: 95 }, (e, i) => String.fromCharCode(i + 32)).join('');
console.log(asciiChars)
let str = '';// empty string declear
for( var i = 32; i <= 126; i++ )
{
str = str + String.fromCharCode( i ); /* this method received one integer and
convert it into a ascii characters and store it str variable one by one by using
string concatenation method. The loop start for 32 and end 126 */
}
Here is a version in coffeescript
require 'fluentnode'
all_Ascii = ->
(String.fromCharCode(c) for c in [0..255])
describe 'all Ascii', ->
it 'all_Ascii', ->
all_Ascii.assert_Is_Function()
all_Ascii().assert_Size_Is 256
all_Ascii()[0x41].assert_Is 'A'
all_Ascii()[66 ].assert_Is 'B'
all_Ascii()[50 ].assert_Is '2'
all_Ascii()[150 ].assert_Is String.fromCharCode(150)