Caesar Cipher in Javascript - javascript

I am trying to write a program to solve the following problem in javascript (Written below this paragraph). I don't know why my code isn't working. Could someone help me? I'm new to javascript; this is a free code camp question.
"A common modern use is the ROT13 cipher, where the values of the letters are shifted by 13 places. Thus 'A' ↔ 'N', 'B' ↔ 'O' and so on.
Write a function which takes a ROT13 encoded string as input and returns a decoded string."
function rot13(str) { // LBH QVQ VG!
var string = "";
for(var i = 0; i < str.length; i++) {
var temp = str.charAt(i);
if(temp !== " " || temp!== "!" || temp!== "?") {
string += String.fromCharCode(13 + String.prototype.charCodeAt(temp));
} else {
string += temp;
}
}
return string;
}
// Change the inputs below to test
console.log(rot13("SERR PBQR PNZC")); //should decode to "FREE CODE CAMP"

Using modulus operator; makes the sentence uppercase;
function cipherRot13(str) {
str = str.toUpperCase();
return str.replace(/[A-Z]/g, rot13);
function rot13(correspondance) {
const charCode = correspondance.charCodeAt();
//A = 65, Z = 90
return String.fromCharCode(
((charCode + 13) <= 90) ? charCode + 13
: (charCode + 13) % 90 + 64
);
}
}

I have tried to make it simple and I earned FREE PIZZA!. Check my solution for this.
function rot13(str) {
var alphabets =['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 alphabets13 = ['N','O','P','Q','R','S','T','U','V','W','X','Y','Z','A','B','C','D','E','F','G','H','I','J','K','L','M', " ", "-", "_", ".", "&","?", "!", "#", "#", "/"];
var resultStr = [];
for(let i=0; i<str.length; i++){
for(let j =0; j<alphabets.length; j++){
if(str[i] === alphabets[j]){
resultStr.push(alphabets13[j]);
}
}
}
return resultStr.join("");
};
rot13("SERR CVMMN!");

You can build the algorithm for ROT13 directly... or just use a Caesar Cipher algorithm with the appropriate key.
The alternative that I'm proposing to your example is just a particular usage of a regular Caesar Cipher algorithm – a very simple form of encryption, in which each letter in the original message is shifted to the left or right by a certain number of positions.
To decrypt the message we simply shift back the letters the same number of positions.
Example:
JAVASCRIPT becomes MDYDVFULSW if we shift all letters by 3 positions
MDYDVFULSW turns back to JAVASCRIPT if we shift back all letters by 3 positions.
If after shifting a letter goes outside the range of letters, then the letter is wrapped around in alphabet. Example: Letter Z becomes C if is shifted by 3 positions.
This “wrap-around” effect means use of modulo. In mathematical terms, the above can be expressed as this:
En(x) = (x + n) mod 26
Dn(x) = (x – n) mod 26
Trying to implement this algorithm in JavaScript without the use of a proper modulo operator will produce either incorrect results or a very cryptic and difficult to understand code.
The biggest problem is that JavaScript doesn't contain a modulo operator. The % operator is just the reminder of the division - not modulo. However, it is pretty easy to implement modulo as a custom function:
// Implement modulo by replacing the negative operand
// with an equivalent positive operand that has the same wrap-around effect
function mod(n, p)
{
if ( n < 0 )
n = p - Math.abs(n) % p;
return n % p;
}
There are other ways of implementing modulo... if you are interested you can consult this article.
By using the mod function defined above, the code expresses the mathematical equation identically:
// Function will implement Caesar Cipher to
// encrypt / decrypt the msg by shifting the letters
// of the message acording to the key
function encrypt(msg, key)
{
var encMsg = "";
for(var i = 0; i < msg.length; i++)
{
var code = msg.charCodeAt(i);
// Encrypt only letters in 'A' ... 'Z' interval
if (code >= 65 && code <= 65 + 26 - 1)
{
code -= 65;
code = mod(code + key, 26);
code += 65;
}
encMsg += String.fromCharCode(code);
}
return encMsg;
}
To encode using ROT13 ... is now just a matter of choosing the appropriate key as indicated by algorithm name.

2020 TypeScript Version:
A shift argument must be given, but you can choose 13 for rot13 or any other number.
// TypeScript Type: Alphabet
type Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Helper Function: Caesar Cipher
export const caesarCipher = (string: string, shift: number) => {
// Alphabet
const alphabet: Alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// Encoded Text
let encodedText: string = '';
// Adjust Shift (Over 26 Characters)
if (shift > 26) {
// Assign Remainder As Shift
shift = shift % 26;
}
// Iterate Over Data
let i: number = 0;
while (i < string.length) {
// Valid Alphabet Characters
if (alphabet.indexOf(string[i]) !== -1) {
// Find Alphabet Index
const alphabetIndex: number = alphabet.indexOf((string[i]).toUpperCase());
// Alphabet Index Is In Alphabet Range
if (alphabet[alphabetIndex + shift]) {
// Append To String
encodedText += alphabet[alphabetIndex + shift];
}
// Alphabet Index Out Of Range (Adjust Alphabet By 26 Characters)
else {
// Append To String
encodedText += alphabet[alphabetIndex + shift - 26];
}
}
// Special Characters
else {
// Append To String
encodedText += string[i];
}
// Increase I
i++;
}
return encodedText;
};
Example #1:
console.log(caesarCipher('ABCDEFGHIJKLMNOPQRSTUVWXYZ', 2));
Output:
CDEFGHIJKLMNOPQRSTUVWXYZAB
Example #2:
console.log(caesarCipher('GUR DHVPX OEBJA QBT WHZCRQ BIRE GUR YNML SBK.', 26 + 13));
Output:
THE QUICK BROWN DOG JUMPED OVER THE LAZY FOX.

I just recently solved a caesar cipher algorithm problem that works similarly to your rot13, but will take any integer value as a shift parameter. One of the issues I notice with your code is you are already assigning temp as a number by assigning the charCode for the character at 'i'. This makes your conditional obsolete, since it will never identify the string values, since you're passing in a number value. Also, when you build the string, it should just be 'String.fromCharCode(13 + temp)'. I personally prefer the caesar cipher, since you can assign random shift parameters.
Here's an example of how I wrote it:
// s = string to encrypt, k = shift value
// s = 'SERR PBQR PNZC' and k = 13 will produce 'FREE CODE CAMP'
const caesarCipher = function(s, k) {
let result = '';
for (let i = 0; i < s.length; i++) {
let charCode = s[i].charCodeAt();
// check that charCode is a lowercase letter; automatically ignores non-letters
if (charCode > 96 && charCode < 123) {
charCode += k % 26 // makes it work with numbers greater than 26 to maintain correct shift
// if shift passes 'z', resets to 'a' to maintain looping shift
if (charCode > 122) {
charCode = (charCode - 122) + 96;
// same as previous, but checking shift doesn't pass 'a' when shifting negative numbers
} else if (charCode < 97) {
charCode = (charCode - 97) + 123;
}
}
if (charCode > 64 && charCode < 91) {
charCode += k % 26
if (charCode > 90) {
charCode = (charCode - 90) + 64;
} else if (charCode < 65) {
charCode = (charCode - 65) + 91;
}
}
result += String.fromCharCode(charCode);
}
return result
}

Note : This function will take care of alphabetic(a-z or A-Z) and all others will be ignored.
Considered points are
Handle negative number
Can take care of big number.
Handle special character, number and space will print as it is
sd
function caesarCipher(word, next) {
next = next % 26;
let res = "";
for (const letter of word) {
let letterCode = letter.charCodeAt(0);
if (letterCode >= 65 && letterCode <= 90) {
letterCode = letterCode + next;
if (letterCode > 90) {
letterCode = letterCode - 26;
} else if (letterCode < 65) {
letterCode = letterCode + 26;
}
} else if (letterCode >= 97 && letterCode <= 122) {
letterCode = letterCode + next;
if (letterCode > 122) {
letterCode = letterCode - 26;
} else if (letterCode < 97) {
letterCode = letterCode + 26;
}
}
res = res + String.fromCharCode(letterCode);
}
return res; }
console.log(caesarCipher("Zoo Keeper 666 %^&*(", 2));
console.log(caesarCipher("Big Car", -16));
Output
Bqq Mggrgt 666 %^&*(
Lsq Mkb

Here's a simple solution.
function caesar(str) {
str = str.split("")
str = str.map(char => {
let code = char.charCodeAt(0)
if( (code > 64 && code < 78) || (code > 96 && code < 110) )
code += 13
else if ( (code > 77 && code < 91) || (code > 109 && code < 123) )
code -= 13
return String.fromCharCode(code)
})
return str.join("")
}

const rot13 = (string) => {
// creating *letterBox* - string in alphabetic way
const letterBox = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
// declaring *iter function* - that will pass through the text
const iter = (str, acc) => {
// if length of string is 0 (phrase is empty) => returning *accumulator*
if (str.length===0) { return acc; }
/* if is not an uppercase character => calling *function iter* by itself
with the new string minus first letter and adding to *accumulator*
without coding symbol */
if (! /^[A-Z]*$/.test(str[0])) {return iter(str.substring(1), acc+str[0]); };
// and now we loop through the uppercase letters (26 letters)
//checking their index in our *letterBox*
// if it's more that 13 , we add 13 , else we substract 13 and
// and of course... calling *iter function* with new string minus first character
// plus *accumumator*
for (let i=0; i<26;i++)
{
if ( (letterBox[i]===str[0]) && (i>12))
{ return iter(str.substring(1), acc + letterBox[i-13]); }
if ( (letterBox[i]===str[0])&& (i<13))
{ return iter(str.substring(1), acc + letterBox[i+13]); };
};
};
// calling *iter function* with the provided *string* and empty *accumulator*
return iter(string,'');
};
console.log(rot13('GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT.'));
// THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG.
passed with success test on codecamp.
also there is another version.. without iter function
const rot13=(str) =>
{
var alph= "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let result ='';
while(str.length>0)
{
for (let i=0;i<=25;i++)
{
if ((alph[i]===str[0]) && (i>13)) {result = result + alph[i-13];};
if ((alph[i]===str[0]) && (i<13)) {result = result + alph[i+13] ;} ;
};
if (! /^[A-Z]*$/.test(str[0]) ) {result = result+ str[0];};
str=str.substring(1);
};
return result;
};
console.log(rot13('SERR YBIR?'));
// returns FREE LOVE?

I am recently in my first stage of developing a javascript library to simplify my daily programming requirements.
One of which is Encryption.
The library uses caesar encryption as of now.
You may download the minified version in the early development and use it in your html pages as:
d(window).loaded(function() {
/* *
* Tidy up the heading
* */
d("h1")
.background("#fafafa")
.color("orange");
/* *
* Encrypt all paragraphs and maximize the height so we view each paragraph separately
* */
d("p")
.encrypt(text = "", depth = 15)
.resize("60%", "50px");
/* *
* Show up the first paragraph element's html
* */
_.popUp("First Paragraph: <hr>" + dom("p").getText(), "", "purple")
})
/* *
* Show the inputed text in below snippet
* */
function showEncryptedText(){
d("#encrypted")
.encrypt(d("#plain").c[0].value, 15)
.background("#e8e8e8")
.resize("100%", "100px");
}
<!DOCTYPE HTML>
<html>
<head>
<title>Element Encryption</title>
<script type="text/javascript" src="https://raw.githubusercontent.com/Amin-Matola/domjs/master/dom-v1.0.0/dom.min.js"></script>
</head>
<body>
<h1>Javascript Encryption</h1>
<p>This is the first paragraph you may encrypt</p>
<p>This is another paragraph you may encrypt</p>
<p>You may encrypt this too</p>
<h2>You may even provide your text to be encrypted</h2>
<div id="encrypted">
</div>
<input type="text" id="plain" value="" name="mydata" oninput="showEncryptedText()"/>
</div>
<footer>
<!--- you may place your js here --->
<script type="text/javascript">
</script>
</body>
</html>

I just solved the caesar chipper problem using this algorithm.
function rot13(str) {
const rot13 = {
'N': "A",
'O': 'B',
'P': 'C',
'Q': 'D',
'R': 'E',
'S': 'F',
'T': 'G',
'U': 'H',
'V': 'I',
'W': 'J',
'X': 'K',
'Y': 'L',
'Z': 'M',
'A': 'N',
'B': 'O',
'C': 'P',
'D': 'Q',
'E': 'R',
'F': 'S',
'G': 'T',
'H': 'U',
'I': 'V',
'J': 'W',
'K': 'X',
'L': 'Y',
'M': 'Z'
}
const splitStr = str.split(' ').map(string => {
return string.split('').map(string => rot13[string] === undefined ? string : rot13[string]).join('');
}).join(' ');
return splitStr;
}

I see that people here have written lengthy codes. I have solved the problem using a simple solution.
function replacing(str){
let strAm = "ABCDEFGHIJKLMNOPQRSTUVWXYZ -_.&?!# #/";
let strNz = "NOPQRSTUVWXYZABCDEFGHIJKLM -_.&?!# #/";
let rot13 = '';
for (let i = 0; i < str.length; i++){
if (strAm.includes(str.charAt(i))){
rot13 += str.charAt(i).replace(str.charAt(i), strNz[strAm.indexOf(str.charAt(i))]);
}
}
return rot13;
}
console.log(replacing("GUR DHVPX OEBJA SBK WHZCF BIRE GUR YNML QBT."));

This problem can be solved in many ways.
Below is the code using ASCII code of the characters in ths string and with two built in JavaScript functions i.e., charCodeAt() and String.fromCharCode()
function rot13(message) {
let cipherString = '';
let arr = [...message];
for (let i = 0; i < arr.length; i++) {
let asciiValue = arr[i].charCodeAt();
if (
(asciiValue >= 65 && asciiValue <= 90) ||
(asciiValue >= 97 && asciiValue <= 122)
) {
if (asciiValue >= 65 && asciiValue <= 90) {
if (asciiValue <= 77) {
asciiValue += 13;
} else {
asciiValue -= 13;
}
} else {
if (asciiValue <= 109) {
asciiValue += 13;
} else {
asciiValue -= 13;
}
}
cipherString += String.fromCharCode(asciiValue);
} else cipherString += arr[i];
}
return cipherString;
}

I wanted to post my way to do it in typestcript.
function caesarCipher(s: string, k: number): string {
//[ [ 'A', 65 ], [ 'Z', 90 ], [ 'a', 97 ], [ 'z', 122 ] ]
return [...s]
.map(l => (l.charCodeAt(0)))
.map(n => n >= 65 && n <= 90 ? ((n - 65 + k) % 26) + 65 : n)
.map(n => n >= 97 && n <= 122 ? ((n - 97 + k) % 26) + 97 : n)
.map(n => String.fromCharCode(n))
.join("")
}

Solution using for loop, in each iteration check if character is alphabet then decode it by subtracting 13 from it's ascii code, if decoded character is not alphabet (its ascii code is less than 65), then decode it by adding 13 to it.
function rot13(str) {
function isAlphabet(char) {
return String(char).match(/[A-Z]/);
}
const chars = str.split("");
for(let i = 0 ; i < chars.length; i++) {
const char = chars[i];
if(isAlphabet(char)) {
const decoded = String.fromCharCode(char.charCodeAt() - 13);
const decodedAlphabet = String.fromCharCode(char.charCodeAt() + 13);
chars[i] = isAlphabet(decoded)? decoded : decodedAlphabet;
}
}
return chars.join("")
}

Here is my approach - provide input and shift.
It maintains lower or upper case of original input and leave unprocessable letters in place:
ceasarCipher("Hello Stackoverflow!");
// Khoor Vwdfnryhuiorz!
function ceasarCipher(input: string, shift = 3) {
const letters = input.split("");
const anyLetter = /[a-z]/i;
return letters
.map((letter) => {
if (!anyLetter.test(letter)) return letter;
const upperLetter = letter.toUpperCase();
const wasOriginalUpper = letter === upperLetter;
const charCode = upperLetter.charCodeAt(0);
//A = 65, Z = 90
const maskedLetter = String.fromCharCode(
charCode + shift <= 90
? charCode + shift
: ((charCode + shift) % 90) + 64
);
if (wasOriginalUpper) {
return maskedLetter;
}
return maskedLetter.toLowerCase();
})
.join("");
}

Simple Implementation of Caesar's Cipher(From FREE CODE CAMP)
function rot13(str) {
const alpha="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
let ans="";
for(let i=0;i<str.length; i++){
const char=str[i];
if(char===" " || char==="!" || char==="?" || char==="."){
ans+=char;
}
else{
const val=alpha.indexOf(str[i]);
const new_val=(val+13)%26;
ans+=alpha[new_val];
}
}
return ans;
}
console.log(rot13("SERR PBQR PNZC"));

While A + 13 may equal N, Z + 13 will not compute correctly.

Related

Caesar Cipher technique and reverse case in javascript

I am beginner and want to make my own function.
I want to hash the password by shifting every character by given x
positions and reverse to lowercase/uppercase.
I think the code below should return "EFGH7654" but it return 55 with no error message.
How can I fix it? Is it because of I put a function in a function?
Or I type wrong any thing?
function hashPassword(password, x) {
// password is a string, x is a number
// return a string
// (ex. password = 'ab1By', x = 3 so it should return "DE4eB")
function shift(text, s) {
result = "";
for (let i = 0; i < text.length; i++) {
let char = text[i];
if (char.toUpperCase(text[i])) {
let ch = String.fromCharCode((char.charCodeAt(0) + s - 65) % 26 + 65);
result += ch;
} else {
let ch = String.fromCharCode((char.charCodeAt(0) + s - 97) % 26 + 97);
result += ch;
}
}
return result;
}
function reversecase(x) {
var output = '';
for (var i = 0, len = x.length; i < len; i++) {
var character = x[i];
if (character == character.toLowerCase()) {
// The character is lowercase
output = output + character.toUpperCase();
} else {
// The character is uppercase
output = output + character.toLowerCase();
}
}
return output
}
var str = "";
var result = "";
var charcode = "";
for (var i = 0; i < password.length; i++) {
if (typeof password[i] === typeof str) {
char = shift(password[i], x)
charcode = reversecase(char)
result += charcode;
} else {
num = password[i] + x
number = num % 10
result += number.toString()
}
}
return result
};
console.log(hashPassword("abcd4321", 4))
There a quite some problems in your code.
The first problem here is not only the nesting, but the fact that you're defining the result variable in the outer function scope using the var keyword. Then you use (read/write) that variable in different places.
In function shift() (also in return statement)
In the outer function (also in return statement)
The thing you have to understand is, that you're referring to the same variable result every time. To ensure that your variables are scoped, i.e. are only valid within a block (if statement, function body, etc.), you should use the let or const keywords. This makes your code a lot safer.
The second problem are some assumptions you make regarding data types. If you have a string let s = "my string 123", the expression typeof s[x] === 'string' will be true for every x in s.
Another problem is the algorithm itself. The outer function hashPassword() iterates over all characters of the input string. Within that loop you call function shift(password[i], x), passing a single character. The first parameter of shift() is called text - and there is another for loop (which is confusing and does not make sense).
To make things short, please have a look at this simplified version:
function shift(char, x) {
let result;
const code = char.charCodeAt(0);
if (code >= 65 && code < 91) {
result = String.fromCharCode((code + x - 65) % 26 + 65);
}
else if (code >= 48 && code <= 57) {
result = String.fromCharCode((code + x - 48) % 10 + 48);
}
else {
result = String.fromCharCode((code + x - 97) % 26 + 97);
}
return result;
}
function reverseCase(character) {
if (character === character.toLowerCase()) {
return character.toUpperCase();
}
else {
return character.toLowerCase();
}
}
function hashPassword(password, x) {
let result = "";
for (let i = 0; i < password.length; i++) {
const char = shift(password[i], x);
result += reverseCase(char);
}
return result;
}
console.log(hashPassword("abcd4321", 4)); // Output: EFGH8765

Need help solving a javascript Caesar Cipher problem

I'm stuck doing the Caesar cipher problem. For those of you familiar with the problem, I'm not able to wrap around the alphabet, for example if I want to shift the string 'z' by 1, instead of getting 'a', i'll get '['. I know the reason this happens but I'm not able to come up with the proper code. Any help will be appreciated.
Here's my code:
const caesar = function(word, num) {
let solved = ""
num = num % 26;
for (let i = 0; i < word.length ; i++) {
let ascii = word[i].charCodeAt();
if ((ascii >= 65 && ascii <= 90) || (ascii >= 97 && ascii <= 122)) {
solved += String.fromCharCode(ascii + num) ;
} else {
solved += word[i]
}
}
return solved;
}
You need to take the modulus under 26 after subtracting the char code of the first letter of the alphabet and add it back afterward to allow the cipher to wrap around. You will need to handle capital and lowercase letters separately.
const caesar = function(word, num) {
let solved = ""
num = (num%26 + 26) % 26;
for (let i = 0; i < word.length ; i++) {
let ascii = word[i].charCodeAt();
if ((ascii >= 65 && ascii <= 90)) {
solved += String.fromCharCode((ascii - 'A'.charCodeAt(0) + num)%26
+ 'A'.charCodeAt(0)) ;
} else if(ascii >= 97 && ascii <= 122){
solved += String.fromCharCode((ascii-'a'.charCodeAt(0) + num) % 26
+ 'a'.charCodeAt(0));
} else {
solved += word[i]
}
}
return solved;
}
console.log(caesar("abcdefghijklmnopqrstuvwxyzABCDEFGHI", 7));
Do the modulus when you add num to your ascii value. This way you don't scroll past the end of the range (and loop around if you are through the modulus (remainder)).
solved += String.fromCharCode((ascii + num)%26) ;
Out of interest, the ASCII codes for 'A` and 'a' are 0x41 and 0x61 respectively: upper and lower case letters differ by whether bit 0x20 is set (lower case) or not set (upper case).
Hence a bit-bashing algorithm to circular shift ASCII letters and maintain case would be strip the lower case bit, perform the shift, and re-insert the case bit:
"use strict";
function caesarShiftLetter( letter, num) {
let code = letter.charCodeAt(0);
let lowerCaseBit = code & 0x20; // 0 or 0x20
let upperCaseCode = code - lowerCaseBit;
if( upperCaseCode < 0x41 || upperCaseCode >= 0x41 + 26) {
return letter;
}
num = 26 + num%26; // handle large negative shift values
upperCaseCode = ((upperCaseCode - 0x41) + num) % 26 + 0x41;
return String.fromCharCode( upperCaseCode | lowerCaseBit);
}
// to test:
function caesarShiftString( str, num) {
return Array.from(str).map(char => caesarShiftLetter( char, num)).join('');
}
console.log( caesarShiftString(
"abc ... xyz, ABC ... XYZ, I, II, III, IV, V, VI, VII, VIII, IX, X - 1,3,4,5,6,7,9, 10",-22
)
);

My decipher call is returning an invalid response when trying to implement Ceasar cipher, why?

functionmovingShift() performs a variation of the Caesar shift. The shift increases by 1 for each character (including spaces character).
Function demovingShift() should decipher returned string backwards.
I can't figure out the algorithm to decipher the returned string.
My code works only for the first few words. Then as "shift" variable grows negative the logic breaks.
let u = "I should have known that you would have a perfect answer for me!!!";
function movingShift(s, shift) {
let arr = [];
s.split("").forEach((x, idx) => {
let source = x.toUpperCase().charCodeAt(0);
if (source < 65 || source > 90) {
arr.push(x);
shift++;
return;
}
let index = (source - 65 + (shift)) % 26 + 65;
let letter = String.fromCharCode(index);
x === x.toLowerCase() ? arr.push(letter.toLowerCase()) : arr.push(letter);
shift++;
})
let cipher = arr.join("");
return cipher;
}
let v = movingShift(u, 1);
function demovingShift(v, shift) {
shift = -1;
let arr = [];
v.split("").forEach((x, idx) => {
let source = x.toUpperCase().charCodeAt(0);
if (source < 65 || source > 90) {
arr.push(x);
shift--;
return;
}
let index = (source - 65 + (shift)) % 26 + 65;
let letter = String.fromCharCode(index);
x === x.toLowerCase() ? arr.push(letter.toLowerCase()) : arr.push(letter);
shift--;
})
return arr.join("");
}
console.log(movingShift(u, 1));
console.log(demovingShift(v, 1));
Returned string from the first function :
J vltasl rlhr zdfog odxr ypw atasl rlhr p gwkzzyq zntyhv lvz wp!!!
Returned string from decipher function:
I sho;ld ha<e k45=4 :.a: ?5; =5;2* .a<+ a 6+8,+): a49=+8 ,58 3+!!!
There are two mistakes in your code.
1) First inside demovingShift you need to change shift = -1 to shift = -1 * shift;.
2) Change let index = (source - 65 + (shift)) % 26 + 65; to let index = (source - 65 + (shift)) % 26 + 65; because now shift is negative its possible that (source - 65 + (shift)) value may became negative which will give incorrect character. So we can use (source + 65 + (shift)).
You can test it below.
let u = "I should have known that you would have a perfect answer for me!!!";
function movingShift(s, shift) {
let arr = [];
s.split("").forEach((x, idx) => {
let source = x.toUpperCase().charCodeAt(0);
if (source < 65 || source > 90) {
arr.push(x);
shift++;
return;
}
let index = (source - 65 + (shift)) % 26 + 65;
let letter = String.fromCharCode(index);
x === x.toLowerCase() ? arr.push(letter.toLowerCase()) : arr.push(letter);
shift++;
})
let cipher = arr.join("");
return cipher;
}
function demovingShift(v, shift) {
shift = -1 * shift;
let arr = [];
v.split("").forEach((x, idx) => {
let source = x.toUpperCase().charCodeAt(0);
if (source < 65 || source > 90) {
arr.push(x);
shift--;
return;
}
let index = (source + 65 + (shift)) % 26 + 65;
let letter = String.fromCharCode(index);
x === x.toLowerCase() ? arr.push(letter.toLowerCase()) : arr.push(letter);
shift--;
})
return arr.join("");
}
let v = movingShift(u, 1);
console.log(u);
console.log(v);
console.log(demovingShift(v, 1));

convert alphabets to coresponding numbers

i have to convert alphabets to corresponding numbers like i have a data like "DRSG004556722000TU77" and the index for A is 10, B is 11, C is 12 and so on up to Z is 35.
any helping tips??
here is the javascript which return me ascii code but i want to get the above indecies for respective alphabet
var string = DRSG004556722000TU77;
function getColumnName(string) {
return ((string.length - 1) * 26) + (string.charCodeAt(string.length - 1) - 64);
}
document.write( getColumnName(string) );
This may help
var output = [], code, str = 'DRSG004556722000TU77',i;
for(i in str){
code = str.charCodeAt(i);
if(code <= 90 && code >= 65){
// Add conditions " && code <= 122 && code >= 97" to catch lower case letters
output.push([i,code]);
}
}
Now ouput contains all letters codes and their corresponding indexes
var string = 'DRSG004556722000TU77';
function getColumnName(string) {
var recode = new Array(), i, n = string.length;
for(i = 0; i < n; i++) {
recode.push(filter(string.charCodeAt(i)));
}
return recode;
}
function filter(symbol) {
if ((symbol >= 65) && (symbol <= 90)) {
return symbol - 55;
} else if ((symbol >= 48) && (symbol <= 57)) {
return symbol - 48;
}
}
document.write(getColumnName(string));

Convert long number into abbreviated string in JavaScript, with a special shortness requirement

In JavaScript, how would one write a function that converts a given [edit: positive integer] number (below 100 billion) into a 3-letter abbreviation -- where 0-9 and a-z/A-Z are counting as a letter, but the dot (as it's so tiny in many proportional fonts) would not, and would be ignored in terms of the letter limit?
This question is related to this helpful thread, but it's not the same; for instance, where that function would turn e.g. "123456 -> 1.23k" ("123.5k" being 5 letters) I am looking for something that does "123456 -> 0.1m" ("0[.]1m" being 3 letters). For instance, this would be the output of hoped function (left original, right ideal return value):
0 "0"
12 "12"
123 "123"
1234 "1.2k"
12345 "12k"
123456 "0.1m"
1234567 "1.2m"
12345678 "12m"
123456789 "0.1b"
1234567899 "1.2b"
12345678999 "12b"
Thanks!
Update: Thanks! An answer is in and works per the requirements when the following amendments are made:
function abbreviateNumber(value) {
var newValue = value;
if (value >= 1000) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor( (""+value).length/3 );
var shortValue = '';
for (var precision = 2; precision >= 1; precision--) {
shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
if (dotLessShortValue.length <= 2) { break; }
}
if (shortValue % 1 != 0) shortValue = shortValue.toFixed(1);
newValue = shortValue+suffixes[suffixNum];
}
return newValue;
}
Approach 1: Built-in library
I would recommend using Javascript's built-in library method Intl.NumberFormat
Intl.NumberFormat('en-US', {
notation: "compact",
maximumFractionDigits: 1
}).format(2500);
Approach 2: No library
But you can also create these abbreviations with simple if statements, and without the complexity of Math, maps, regex, for-loops, etc.
Formatting Cash value with K
const formatCash = n => {
if (n < 1e3) return n;
if (n >= 1e3) return +(n / 1e3).toFixed(1) + "K";
};
console.log(formatCash(2500));
Formatting Cash value with K M B T
const formatCash = n => {
if (n < 1e3) return n;
if (n >= 1e3 && n < 1e6) return +(n / 1e3).toFixed(1) + "K";
if (n >= 1e6 && n < 1e9) return +(n / 1e6).toFixed(1) + "M";
if (n >= 1e9 && n < 1e12) return +(n / 1e9).toFixed(1) + "B";
if (n >= 1e12) return +(n / 1e12).toFixed(1) + "T";
};
console.log(formatCash(1235000));
Using negative numbers
let format;
const number = -1235000;
if (number < 0) {
format = '-' + formatCash(-1 * number);
} else {
format = formatCash(number);
}
I believe ninjagecko's solution doesn't quite conform with the standard you wanted. The following function does:
function intToString (value) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor((""+value).length/3);
var shortValue = parseFloat((suffixNum != 0 ? (value / Math.pow(1000,suffixNum)) : value).toPrecision(2));
if (shortValue % 1 != 0) {
shortValue = shortValue.toFixed(1);
}
return shortValue+suffixes[suffixNum];
}
For values greater than 99 trillion no letter will be added, which can be easily fixed by appending to the 'suffixes' array.
Edit by Philipp follows: With the following changes it fits with all requirements perfectly!
function abbreviateNumber(value) {
var newValue = value;
if (value >= 1000) {
var suffixes = ["", "k", "m", "b","t"];
var suffixNum = Math.floor( (""+value).length/3 );
var shortValue = '';
for (var precision = 2; precision >= 1; precision--) {
shortValue = parseFloat( (suffixNum != 0 ? (value / Math.pow(1000,suffixNum) ) : value).toPrecision(precision));
var dotLessShortValue = (shortValue + '').replace(/[^a-zA-Z 0-9]+/g,'');
if (dotLessShortValue.length <= 2) { break; }
}
if (shortValue % 1 != 0) shortValue = shortValue.toFixed(1);
newValue = shortValue+suffixes[suffixNum];
}
return newValue;
}
This handles very large values as well and is a bit more succinct and efficient.
abbreviate_number = function(num, fixed) {
if (num === null) { return null; } // terminate early
if (num === 0) { return '0'; } // terminate early
fixed = (!fixed || fixed < 0) ? 0 : fixed; // number of decimal places to show
var b = (num).toPrecision(2).split("e"), // get power
k = b.length === 1 ? 0 : Math.floor(Math.min(b[1].slice(1), 14) / 3), // floor at decimals, ceiling at trillions
c = k < 1 ? num.toFixed(0 + fixed) : (num / Math.pow(10, k * 3) ).toFixed(1 + fixed), // divide by power
d = c < 0 ? c : Math.abs(c), // enforce -0 is 0
e = d + ['', 'K', 'M', 'B', 'T'][k]; // append power
return e;
}
Results:
for(var a='', i=0; i < 14; i++){
a += i;
console.log(a, abbreviate_number(parseInt(a),0));
console.log(-a, abbreviate_number(parseInt(-a),0));
}
0 0
-0 0
01 1
-1 -1
012 12
-12 -12
0123 123
-123 -123
01234 1.2K
-1234 -1.2K
012345 12.3K
-12345 -12.3K
0123456 123.5K
-123456 -123.5K
01234567 1.2M
-1234567 -1.2M
012345678 12.3M
-12345678 -12.3M
0123456789 123.5M
-123456789 -123.5M
012345678910 12.3B
-12345678910 -12.3B
01234567891011 1.2T
-1234567891011 -1.2T
0123456789101112 123.5T
-123456789101112 -123.5T
012345678910111213 12345.7T
-12345678910111212 -12345.7T
The modern, easy, built-in, highly customizable, and 'no-code' way: Intl.FormatNumber 's format function (compatibility graph)
var numbers = [98721, 9812730,37462,29,093484620123, 9732,0283737718234712]
for(let num of numbers){
console.log(new Intl.NumberFormat( 'en-US', { maximumFractionDigits: 1,notation: "compact" , compactDisplay: "short" }).format(num));
}
98.7K
9.8M
37.5K
29
93.5B
9.7K
283.7T
Notes:
If you're using typescript add a //#ts-ignore before notation (source)
And a list of all the keys in the options parameter: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters
When using style: 'currency', you must remove maximumFractionDigits, as it will figure this out for you.
Here's what I think is a fairly elegant solution. It does not attempt to deal with negative numbers:
const COUNT_ABBRS = [ '', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' ];
function formatCount(count, withAbbr = false, decimals = 2) {
const i = 0 === count ? count : Math.floor(Math.log(count) / Math.log(1000));
let result = parseFloat((count / Math.pow(1000, i)).toFixed(decimals));
if(withAbbr) {
result += `${COUNT_ABBRS[i]}`;
}
return result;
}
Examples:
formatCount(1000, true);
=> '1k'
formatCount(100, true);
=> '100'
formatCount(10000, true);
=> '10k'
formatCount(10241, true);
=> '10.24k'
formatCount(10241, true, 0);
=> '10k'
formatCount(10241, true, 1)
=> '10.2k'
formatCount(1024111, true, 1)
=> '1M'
formatCount(1024111, true, 2)
=> '1.02M'
I think you cant try this numeraljs/
If you want convert 1000 to 1k
console.log(numeral(1000).format('0a'));
and if you want convert 123400 to 123.4k try this
console.log(numeral(123400).format('0.0a'));
Based on my answer at https://stackoverflow.com/a/10600491/711085 , your answer is actually slightly shorter to implement, by using .substring(0,3):
function format(n) {
with (Math) {
var base = floor(log(abs(n))/log(1000));
var suffix = 'kmb'[base-1];
return suffix ? String(n/pow(1000,base)).substring(0,3)+suffix : ''+n;
}
}
(As usual, don't use Math unless you know exactly what you're doing; assigning var pow=... and the like would cause insane bugs. See link for a safer way to do this.)
> tests = [-1001, -1, 0, 1, 2.5, 999, 1234,
1234.5, 1000001, Math.pow(10,9), Math.pow(10,12)]
> tests.forEach(function(x){ console.log(x,format(x)) })
-1001 "-1.k"
-1 "-1"
0 "0"
1 "1"
2.5 "2.5"
999 "999"
1234 "1.2k"
1234.5 "1.2k"
1000001 "1.0m"
1000000000 "1b"
1000000000000 "1000000000000"
You will need to catch the case where the result is >=1 trillion, if your requirement for 3 chars is strict, else you risk creating corrupt data, which would be very bad.
Code
const SI_PREFIXES = [
{ value: 1, symbol: '' },
{ value: 1e3, symbol: 'k' },
{ value: 1e6, symbol: 'M' },
{ value: 1e9, symbol: 'G' },
{ value: 1e12, symbol: 'T' },
{ value: 1e15, symbol: 'P' },
{ value: 1e18, symbol: 'E' },
]
const abbreviateNumber = (number) => {
if (number === 0) return number
const tier = SI_PREFIXES.filter((n) => number >= n.value).pop()
const numberFixed = (number / tier.value).toFixed(1)
return `${numberFixed}${tier.symbol}`
}
abbreviateNumber(2000) // "2.0k"
abbreviateNumber(2500) // "2.5k"
abbreviateNumber(255555555) // "255.6M"
Test:
import abbreviateNumber from './abbreviate-number'
test('abbreviateNumber', () => {
expect(abbreviateNumber(0)).toBe('0')
expect(abbreviateNumber(100)).toBe('100')
expect(abbreviateNumber(999)).toBe('999')
expect(abbreviateNumber(1000)).toBe('1.0k')
expect(abbreviateNumber(100000)).toBe('100.0k')
expect(abbreviateNumber(1000000)).toBe('1.0M')
expect(abbreviateNumber(1e6)).toBe('1.0M')
expect(abbreviateNumber(1e10)).toBe('10.0G')
expect(abbreviateNumber(1e13)).toBe('10.0T')
expect(abbreviateNumber(1e16)).toBe('10.0P')
expect(abbreviateNumber(1e19)).toBe('10.0E')
expect(abbreviateNumber(1500)).toBe('1.5k')
expect(abbreviateNumber(1555)).toBe('1.6k')
expect(abbreviateNumber(undefined)).toBe('0')
expect(abbreviateNumber(null)).toBe(null)
expect(abbreviateNumber('100')).toBe('100')
expect(abbreviateNumber('1000')).toBe('1.0k')
})
Here's another take on it. I wanted 123456 to be 123.4K instead of 0.1M
UPDATE 2022, Dec. 5
Added support for negative values and non-integer values
function convert(value) {
var length = (Math.abs(parseInt(value, 10)) + '').length,
index = Math.ceil((length - 3) / 3),
suffix = ['K', 'M', 'B', 'T'];
if (length < 4) return value;
return (value / Math.pow(1000, index))
.toFixed(1)
.replace(/\.0$/, '') + suffix[index - 1];
}
var tests = [1234, 7890, -990123467, 123456, 750000.1234, 567890, 800001, 2000000, 20000000, 201234567, 801234567, 1201234567];
for (var i in tests)
document.writeln('<p>convert(' + tests[i] + ') = ' + convert(tests[i]) + '</p>');
After some playing around, this approach seems to meet the required criteria. Takes some inspiration from #chuckator's answer.
function abbreviateNumber(value) {
if (value <= 1000) {
return value.toString();
}
const numDigits = (""+value).length;
const suffixIndex = Math.floor(numDigits / 3);
const normalisedValue = value / Math.pow(1000, suffixIndex);
let precision = 2;
if (normalisedValue < 1) {
precision = 1;
}
const suffixes = ["", "k", "m", "b","t"];
return normalisedValue.toPrecision(precision) + suffixes[suffixIndex];
}
Intl is the Javascript standard 'package' for implemented internationalized behaviours. Intl.NumberFormatter is specifically the localized number formatter. So this code actually respects your locally configured thousands and decimal separators.
intlFormat(num) {
return new Intl.NumberFormat().format(Math.round(num*10)/10);
}
abbreviateNumber(value) {
let num = Math.floor(value);
if(num >= 1000000000)
return this.intlFormat(num/1000000000)+'B';
if(num >= 1000000)
return this.intlFormat(num/1000000)+'M';
if(num >= 1000)
return this.intlFormat(num/1000)+'k';
return this.intlFormat(num);
}
abbreviateNumber(999999999999) // Gives 999B
Related question: Abbreviate a localized number in JavaScript for thousands (1k) and millions (1m)
I'm using this function to get these values.
function Converter(number, fraction) {
let ranges = [
{ divider: 1, suffix: '' },
{ divider: 1e3, suffix: 'K' },
{ divider: 1e6, suffix: 'M' },
{ divider: 1e9, suffix: 'G' },
{ divider: 1e12, suffix: 'T' },
{ divider: 1e15, suffix: 'P' },
{ divider: 1e18, suffix: 'E' },
]
//find index based on number of zeros
let index = (Math.abs(number).toString().length / 3).toFixed(0)
return (number / ranges[index].divider).toFixed(fraction) + ranges[index].suffix
}
Each 3 digits has different suffix, that's what i'm trying to find firstly.
So, remove negative symbol if exists, then find how many 3 digits in this number.
after that find appropriate suffix based on previous calculation added to divided number.
Converter(1500, 1)
Will return:
1.5K
Use as a Number Prototype
For easy and direct you. Simply make a prototype of it. Here is an example.
Number.prototype.abbr = function (decimal = 2): string {
const notations = ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y'],
i = Math.floor(Math.log(this) / Math.log(1000));
return `${parseFloat((this / Math.pow(1000, i)).toFixed(decimal))}${notations[i]}`;
};
Indian Currency format to (K, L, C) Thousand, Lakh, Crore
const formatCash = n => {
if (n < 1e3) return n;
if (n >= 1e3 && n < 1e5) return +(n / 1e3).toFixed(1) + "K";
if (n >= 1e5 && n <= 1e6) return +(n / 1e5).toFixed(1) + "L";
if (n >= 1e6 && n <= 1e9) return +(n / 1e7).toFixed(1) + "C";
};
Try it :
const unitlist = ['', 'K', 'M', 'B']
export function AmountConveter (number: number) {
const sign = Math.sign(number)
let unit = 0
while (Math.abs(number) > 1000) {
unit = unit + 1
number = Math.floor(Math.abs(number) / 100) / 10
}
return sign * Math.abs(number) + unitlist[unit]
}
function converse_number (labelValue) {
// Nine Zeroes for Billions
return Math.abs(Number(labelValue)) >= 1.0e+9
? Math.abs(Number(labelValue)) / 1.0e+9 + "B"
// Six Zeroes for Millions
: Math.abs(Number(labelValue)) >= 1.0e+6
? Math.abs(Number(labelValue)) / 1.0e+6 + "M"
// Three Zeroes for Thousands
: Math.abs(Number(labelValue)) >= 1.0e+3
? Math.abs(Number(labelValue)) / 1.0e+3 + "K"
: Math.abs(Number(labelValue));
}
alert(converse_number(100000000000));
#nimesaram
Your solution will not be desirable for the following case:
Input 50000
Output 50.0k
Following solution will work fine.
const convertNumberToShortString = (
number: number,
fraction: number
) => {
let newValue: string = number.toString();
if (number >= 1000) {
const ranges = [
{ divider: 1, suffix: '' },
{ divider: 1e3, suffix: 'k' },
{ divider: 1e6, suffix: 'm' },
{ divider: 1e9, suffix: 'b' },
{ divider: 1e12, suffix: 't' },
{ divider: 1e15, suffix: 'p' },
{ divider: 1e18, suffix: 'e' }
];
//find index based on number of zeros
const index = Math.floor(Math.abs(number).toString().length / 3);
let numString = (number / ranges[index].divider).toFixed(fraction);
numString =
parseInt(numString.substring(numString.indexOf('.') + 1)) === 0
? Math.floor(number / ranges[index].divider).toString()
: numString;
newValue = numString + ranges[index].suffix;
}
return newValue;
};
// Input 50000
// Output 50k
// Input 4500
// Output 4.5k
Even more Abbreviation?
Let's make "Qa" as Quadrillions and "Qi" as Quintillions... maybe "Sx" Sextillions, and So on...
if (num >= 1e3 !& num >= 1e6) {num2 = num/1e3 + "K";};
if (num >= 1e6 !& num >= 1e9) {num2 = num/1e6 + "M";};
if (num >= 1e9 !& num >= 1e12) {num2 = num/1e9 + "B";};
if (num >= 1e12 !& num >= 1e15) {num2 = num/1e12 + "T";};
if (num >= 1e15 !& num >= 1e18) {num2 = num/1e15 + "Qa";};
if (num >= 1e18 !& num >= 1e21) {num2 = num/1e18 + "Qi";};
if (num >= 1e21 !& num >= 1e24) {num2 = num/1e21 + "Sx";};
if (num >= 1e24 !& num >= 1e27) {num2 = num/1e24 + "Sp";};
if (num >= 1e27 !& num >= 1e30) {num2 = num/1e27 + "Oc";};
if (num >= 1e30 !& num >= 1e93) {num2 = num/1e30 + "No";};
if (num >= 1e33 !& num >= 1e36) {num2 = num/1e33 + "Dc";};
if (num >= 1e36 !& num >= 1e39) {num2 = num/1e36 + "UDc";};
if (num >= 1e39) {num2 = num/1e39 + "DDc";};
Pure Javascript
n --> 292234567890 to 292,234,567,890
s --> 292,234,567,890 to 292,234,567,890 + K | M | B | T | q | Q | s | S | o | n | d | U
s --> 292,234,567,890B to 292.2B
return --> Remove 4th digit 292.2B to 292B
function format(n) {n=n.toLocaleString();
let s = n+('KMBTqQsSondU'.split('')[n.split(',').length-2]||'')
s = s.replace(/,([1-9])[\d,.]+|,[\d,.]+/g,(m,a)=>a?'.'+a:'')
return s.replace(/(\d{3})\.\d/, '$1');
}
//Just for show
let negative = [-1991078910902345678907890, -991708910902345678907890,-10902345678907890, -1000234567890, -1234567890, -12345678, -1234567, -12345, -1234, -123, -12, -1, 0]
let positive = [1991078910902345678907890, 991078910902345678907890,10902345678907890, 1000234567890, 1234567890, 12345678, 1234567, 12345, 1234, 123, 12, 1, 0]
let table = '<table cellspacing="0"><tbody>';
negative.forEach(function(x){ table += '<tr><td style="padding-right: 30px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
table +='</tbody></table><table cellspacing="0"><tbody>'
positive.forEach(function(x){ table += '<tr><td style="padding-right: 30px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
document.body.innerHTML = table+'</tbody></table>';
tr:nth-child(odd) {background: #f8f8f8;}
td {padding: 5px 10px;}
table {
font-size: 13px;
display: inline-table;
padding-right: 30px;
}
Pure Javascript
Pros: Native Built in Solution
Cons: Maxes out at Trillion
function format(x) {let o={maximumFractionDigits: 1,notation: "compact",compactDisplay: "short"};
let a=x<0,n=x*Math.sign(x);s=new Intl.NumberFormat('en-US', o).format(n);return a?'-'+s:s;
}
//Just for show
let negative = [-1991078910902345678907890, -991078910902345678907890,-10902345678907890, -1000234567890, -1234567890, -12345678, -1234567, -12345, -1234, -123, -12, -1, 0]
let positive = [1991078910902345678907890, 991078910902345678907890,10902345678907890, 1000234567890, 1234567890, 12345678, 1234567, 12345, 1234, 123, 12, 1, 0]
let table = '<table cellspacing="0"><tbody>';
negative.forEach(function(x){ table += '<tr><td style="padding-right: 10px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
table +='</tbody></table><table cellspacing="0"><tbody>'
positive.forEach(function(x){ table += '<tr><td style="padding-right: 10px;">'+x+'</td><td>'+ format(x)+'</td></tr>'})
document.body.innerHTML = table+'</tbody></table>';
tr:nth-child(odd) {background: #f8f8f8;}
td {padding: 5px 10px;}
table {
font-size: 12px;
display: inline-table;
padding-right: 10px;
}

Categories

Resources