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'
Related
I need to implement the .split method in my own way without using prebuilt functions. The method should receive a string divided into 2 sentences by a dot and divide them through a separator.
For example, there is this string:
'word wooord wooooooooord wooooooord. wooooooooord woooooord woooord wooooooooord', separator in this case: '. '
The result should be:
['word wooord wooooooooord wooooooord", "wooooooooord woooooord woooord wooooooooord']
I tried to implement it myself, the first problem I encountered is that the words from the string are added character by character to the new array. The second problem is that the output is still a string even though I declared an array earlier.
function split(str, splitter){
let arrSent = []
for (let i = 0; i < str.length; i++){
if (str[i] != splitter){
arrSent += str[i]
}
}
return arrSent
}
console.log(split('word wooord wooooooooord wooooooord. wooooooooord woooooord woooord wooooooooord', '. '))
Since the delimiter can have more than one character, you need a system to upfront collect a sample of characters (of the same length as the delimiter) to be then compared with the delimiter:
const split = (str, delimiter) => {
// If delimiter is empty string just return an array of characters
if (delimiter === "") return [...str];
const len = delimiter.length;
const iter = str.length - len + 1; // max needed iterations
const arr = [""]; // Prefill it with empty string
let idx = 0; // arr insertion pointer
for (let i = 0; i < iter; i++) {
// Collect len chars from str as a sample
// to compare with the delimiter:
let sample = "";
for (let x = i; x < i + len; x++) {
sample += str[x];
}
const isSplit = sample === delimiter;
const isEnded = i === iter - 1;
if (isSplit) {
i += len - 1; // Consume splitted characters
idx += 1; // Increment arr pointer
arr[idx] = ""; // Prepare the new array key as empty string
} else {
// If loop ended append the entire sample.
// Otherwise, append a single character:
arr[idx] += isEnded ? sample : str[i];
}
}
return arr
}
console.log(split("word. etc", ". "));
console.log(split("word. etc. ", ". "));
console.log(split(". word yep. . etc. ", ". "));
console.log(split("word", ". "));
console.log(split("word", "word"));
console.log(split("word", ""));
console.log(split("", ""));
above, idx (starting at 0) is used as the output's arr insertion pointer. The idx is incremented if the sample matches the delimiter. Also, if there's a match, we need to skip iterations i += len, to not include the delimiter in the output array.
To test, create many examples and right before return arr; use console.log(JSON.stringify(arr) === JSON.stringify(str.split(delimiter))); - it should return true for all the submitted tests.
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("")
$('.creditCardText').keyup(function() {
var foo = $(this).val().split("-").join(""); // remove hyphens
if (foo.length > 0) {
foo = foo.match(new RegExp('.{1,4}', 'g')).join("-");
}
$(this).val(foo);
});
I found this tutorial on putting dash after every 4 character from here my question is what if the character interval is not constant like in this example it is only after every 4 what if the interval is 3 characters "-" 2 characters "-" 4 characters "-" 3 characters "-" so it would appear like this 123-12-1234-123-123.
In this case, it is more convenient to just write normal code to solve the problem:
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
Sample usage:
function format(input, format, sep) {
var output = "";
var idx = 0;
for (var i = 0; i < format.length && idx < input.length; i++) {
output += input.substr(idx, format[i]);
if (idx + format[i] < input.length) output += sep;
idx += format[i];
}
output += input.substr(idx);
return output;
}
$('.creditCardText').keyup(function() {
var foo = $(this).val().replace(/-/g, ""); // remove hyphens
// You may want to remove all non-digits here
// var foo = $(this).val().replace(/\D/g, "");
if (foo.length > 0) {
foo = format(foo, [3, 2, 4, 3, 3], "-");
}
$(this).val(foo);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<input class="creditCardText" />
While it is possible to do partial matching and capturing with regex, the replacement has to be done with a replacement function. In the replacment function, we need to determine how many capturing group actually captures some text. Since there is no clean solution with regex, I write a more general function as shown above.
You can split it using a regular expression. In this case, I'm using a expression to check for non-spaces with interval 3-2-4-3.
The RegExp.exec will return with a "match" array, with the first element containing the actual string. After removing the first element of the match, you can then join them up with dashes.
var mystring = "123121234123"
var myRegexp = /^([^\s]{3})([^\s]{2})([^\s]{4})([^\s]{3})$/g
var match = myRegexp.exec(mystring);
if (match)
{
match.shift();
mystring = match.join("-")
console.log(mystring)
}
Per further comments, the op clarified they need a fixed interval for when to insert dashes. In that case, there are several ways to implement it; I think regular expression would probably be the worst, in other words, overkill and overly complication solution.
Some simpler options would be to create a new character array, and in a loop append character by character, adding a dash too every time you get to the index you want. This would probably be the easiest to write and grok after the fact, but a little more verbose.
Or you could convert to a character array and use an 'insert into array at index'-type function like splice() (see Insert Item into Array at a Specific Index or Inserting string at position x of another string for some examples).
Pass the input value and the indexes to append the separator, first, it will remove the existing separators then just append separators on positions indexes.
export function addSeparators(
input: string,
positions: number[],
separator: string
): string {
const inputValue = input.replace(/-/g, '').split(''); // remove existing separators and split characters into array
for (let i = 0; i < inputValue.length; i++) {
if (positions.includes(i)) inputValue.splice(i, 0, separator);
}
return inputValue.join('');
}
I wrote a simple program to analyze a string to find the word with the greatest amount of duplicate letters within it. It essentially takes a given string, breaks it up into an array of separated words, and then breaks up each separate word into alphabetically sorted groups of individual letters (which are then compared as prev and next, 2 at a time, as the containing array is iterated through). Any two adjacent and matching values found adds one tally to the hash-file next to the word in question, and the word with the most tallied pairs of duplicate letters is returned at the end as greatest. No matching pairs found in any word returns -1. This is what it's supposed to do.
Below, I've run into a problem: If I don't use a REGEXP to replace one of my matched characters, then my code gives false positives as it will count triplicates (eg, "EEE"), as two separate pairs, (eg, "EEE" = "EE & EE", instead of being viewed as "EE, E"). However, if I DO use the REGEXP below to prevent triplicate counts, then doing so breaks my loop mid-stride, and skips to the next word. Is there no way to make this way work? If not, would it be better to employ a REGEXP which deletes all chars EXCEPT the duplicate characters in question, and then perhaps I could divide the .length of each word by 2 to get the number of pairs remaining? Any ideas as to how to solve this would greatly help.
var str = "Helloo aplpplpp pie";
//var str = "no repting letrs";
//var str = "ceoderbyte";
function LetterCountI(str) {
var input = str.split(" ");
console.log(input);
console.log("\n")
var hashObject = {};
var word = "";
var count = 0;
for(var i = 0; i<input.length; i++) {
var currentItem = input[i];
var currentWordIntoChars = currentItem.split("").sort();
console.log(currentWordIntoChars);
var counter = 0;
for(var j=1; j<currentWordIntoChars.length; j++) {
console.log(currentWordIntoChars[j-1] + "=currentChar j-1");
console.log(currentWordIntoChars[j] + "=prev j");
console.log("-");
var final = currentItem;
if(currentWordIntoChars[j-1] == currentWordIntoChars[j]) {
counter++;
hashObject[final] = counter;
//currentWordIntoChars = currentWordIntoChars[j-1].replace(/[a-z]/gi, String.fromCharCode(currentItem.charCodeAt(0)+1));
//HERE REPLACE j-1 with random# or something
//to avoid 3 in a row being counted as 2 pair
//OR use regexp to remove all but pairs, and
//then divide .length/2 to get pairs.
console.log(counter + " === # total char pairs");
}
if(count<hashObject[currentItem]) {
word = final;
count = hashObject[currentItem];
}
}
}
console.log(hashObject);
console.log("\n");
for (var o in hashObject) if (o) return word;
return -1;
}
console.log(LetterCountI(str));
An other way to do it, consists to replace duplicate characters in a sorted word:
var str = "Helloo aplpplpp pie";
function LetterCountI(str) {
var input = str.split(" ");
var count = 0;
var result = -1;
for(var i = 0; i<input.length; i++) {
var nb = 0;
var sortedItem = input[i].split("").sort().join("");
sortedItem.replace(/(.)\1/g, function (_) { nb++ });
if (nb > count) {
count = nb;
result = input[i];
}
}
return result;
}
console.log(LetterCountI(str));
Notes: The replace method is only a way to increment nb using a callback function. You can do the same using the match method and counting results.
if two words have the same number of duplicates, the first word will be returned by default. You can easily change this behaviour with the condition of the if statement.
Whenever you find a match within a word, increment j by 1 to skip comparing the next letter.
var str = "Helloo aplpplpp pie";
//var str = "no repting letrs";
//var str = "ceoderbyte";
function LetterCountI(str)
{
var input = str.split(" ");
console.log(input);
console.log("\n")
var hashObject = {};
var word = "";
var count = 0;
for(var i = 0; i<input.length; i++)
{
var currentItem = input[i];
var currentWordIntoChars = currentItem.split("").sort();
console.log(currentWordIntoChars);
var counter = 0;
for(var j=1; j<currentWordIntoChars.length; j++)
{
console.log(currentWordIntoChars[j-1] + "=currentChar j-1");
console.log(currentWordIntoChars[j] + "=prev j");
console.log("-");
var final = currentItem;
if(currentWordIntoChars[j-1] == currentWordIntoChars[j])
{
counter++;
hashObject[final] = counter;
j++; // ADD HERE
console.log(counter + " === # total char pairs");
}
if(count<hashObject[currentItem])
{
word = final;
count = hashObject[currentItem];
}
}
}
console.log(hashObject);
console.log("\n");
for (var o in hashObject) if (o) return word;
return -1;
}
console.log(LetterCountI(str));
I am trying to figure out how to break up a sting to groups of five and reverse each one individually. I want it to work for any string, (there is no delimiter for splitting)
For example, if the variable is:
Iwanttobreakthisintogroupsoffiveandreverse
I would want it to return:
tnawI erbot ihtka otnis puorg iffos dnaev rever es
How do I go about this?
var str = "Iwanttobreakthisintogroupsoffiveandreverse"
var result = [];
str.replace(/.{1,5}/g, function(m) {
result.push(m.split('').reverse().join(''));
});
result.join(' ');
// "tnawI erbot ihtka otnis puorg iffos dnaev rever es"
var input="Iwanttobreakthisintogroupsoffiveandreverse";
var matches = input.match(/.{1,5}/g);
for (i = 0; i < matches.length; ++i) {
matches[i] = matches[i].split("").reverse().join("");
}
alert(matches);
It pops up tnawI,erbot,ihtka,otnis,puorg,iffos,dnaev,rever,es
You could try this:
var chars = "Iwanttobreakthisintogroupsoffiveandreverse".split('')
var str_rev = []
for (i = 0; i < chars.length; i += 5)
str_rev.push( chars.slice(i, i + 5).reverse().join('') )
Convert to char array using split(''). This allows you to use array methods like reverse and slice
Loop through the char array taking 5 element slices
reverse the elements, join the chars to create a string, and add it to rev_str