5

I have a string called

"Pizza2Day!"

that I want to replace using a array set. In this array set I have the original alphabets as reference

var originalValues = ['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'];

and then I have the encryption key set

var encryptedValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

what I want to do is find any occurrences in the original string "Pizza2Day" of normal alphabets (a,b,c,d) and replace them with their substitutes in the encryption set (m,n,h,f). So the result would be "Njaam2Fmc!"

How would I go about doing this? Will a loop come in handy in this case?

3
  • 4
    Did you tried it by yourself? Commented Mar 23, 2017 at 22:26
  • Use charAt or charCodeAt Commented Mar 23, 2017 at 22:26
  • If you do that you're probably going to replace a with m, and then m with q, etc etc. When you do the replacement put an escape character or something in front of it so that you don't double replace, and then remove the escape at the end. Commented Mar 23, 2017 at 22:27

8 Answers 8

17

Another approach.

var dictionary = { "a": "m", "b": "h", "c": "t", "d": "f", "e": "g", "f": "k", "g": "b", "h": "p", "i": "j", "j": "w", "k": "e", "l": "r", "m": "q", "n": "s", "o": "l", "p": "n", "q": "i", "r": "u", "s": "o", "t": "x", "u": "z", "v": "y", "w": "v", "x": "d", "y": "c", "z": "a", "A": "M", "B": "H", "C": "T", "D": "F", "E": "G", "F": "K", "G": "B", "H": "P", "I": "J", "J": "W", "K": "E", "L": "R", "M": "Q", "N": "S", "O": "L", "P": "N", "Q": "I", "R": "U", "S": "O", "T": "X", "U": "Z", "V": "Y", "W": "V", "X": "D", "Y": "C", "Z": "A" },
    string = "Pizza2Day!",
    result = string.replace(/[a-z]/gi, m => dictionary[m]);
    
    console.log(result);

Sign up to request clarification or add additional context in comments.

6 Comments

This doesn't properly convert uppercase letters.
@4castle What's the problem to just add upper letters into the dictionary?
That would work, but it's not dynamic. You could duplicate all the entries programmatically though.
@4castle It's not dynamic - huh, I don't really know if it's dynamic or not, but it's quick and simple, though.
By "it's not dynamic", I mean that you're hardcoding everything twice, which violates the DRY principle. Of course, your intent with the answer is clear.
|
3

Here's a clean ES6 class solution if you're using Node.js, a JS precompiler, or only care about the latest browsers. This solution also provides clean encrypt and decrypt functions for the cipher.

The use of the dictionary also means this has an O(1) setup cost, and an O(n) encryption and decryption time. This will likely perform quicker than many of the other solutions posted here which repeatedly use linear indexOf searches through the letter arrays.

class Cipher {
    constructor() {
        // TODO: make the letters and values mapping command line args?
        const cipherLetters = ['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'];
        const cipherValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

        this.encryptionKey = {};
        this.decryptionKey = {};

        // build cipher = {a: 'm', b: 'h', ...}
        for (let i=0; i<cipherLetters.length; i+=1) {
            this.encryptionKey[cipherLetters[i]] = cipherValues[i];
            this.encryptionKey[cipherLetters[i].toUpperCase()] = cipherValues[i].toUpperCase();

            this.decryptionKey[cipherValues[i]] = cipherLetters[i];
            this.decryptionKey[cipherValues[i].toUpperCase()] = cipherLetters[i].toUpperCase();
        }
    }

    /**
     * Encrypt some plaintext
     * @param plaintext
     */
    encrypt(plaintext) {
        return plaintext.split('').map(letter => this.encryptionKey[letter] || letter).join('');
    }

    /**
     * Decrypt some cryptotext back into plaintext
     * @param cryptotext
     */
    decrypt(cryptotext) {
        return cryptotext.split('').map(letter => this.decryptionKey[letter] || letter).join('');
    }
}

const cipher = new Cipher();
const plaintext = 'Pizza2Day!';
const encoded = cipher.encrypt(plaintext);
const decoded = cipher.decrypt(encoded);

console.log(plaintext, encoded, decoded);

Comments

2

Here is how I would do it, maybe not the best method but easy to understand

let string = "Pizza2Day!"

let alphabet = "abcdefghijklmnopqrstuvwxyz".split('');
let encrypted = "abcdefghijklmnopqrstuvwxyz".split('').reverse(); //change this to your key

let result = [];

for (let i = 0; i < string.length; i++){
  let tmp = alphabet.indexOf(string[i]); //get index of current letter in the alphabet array.
   //if tmp == -1, the array doesn't contain the character
  if (tmp != -1){
    result.push(encrypted[tmp]); //push the corresponding character from the encrypted array into our result array
  }
  else
    result.push(string[i]);
}

console.log(result.join('')); //join our array back into a string

Hope this helps!

Comments

2

This is what I would do:

const word = "Pizza2Day!";
const originalValues = ['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'];
const encryptedValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

word.split('').map(letter=>{
  const isUpper = letter.toLowerCase() != letter;
  let encryptedLetter = encryptedValues[originalValues.indexOf(letter.toLowerCase())] || letter;
  if(isUpper) encryptedLetter = encryptedLetter.toUpperCase();
  return encryptedLetter;
} ).join('');

1 Comment

If using let, you probably shouldn't be using var; and when using let, you should probably be using const. Justification
1

This is certainly not the most elegant solution, but the logic is easy to follow

var originalValues = ['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 encryptedValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

var str = "Pizza2Day!";
var newStr = "";
var index;

for(var i = 0; i < str.length; i++) {
  index = originalValues.indexOf(str[i].toLowerCase())
  if(index === -1) {
    newStr += str[i];
  } else {
    if(str[i] === originalValues[index].toLowerCase()) {
      newStr += encryptedValues[index];
    } else {
      newStr += encryptedValues[index].toUpperCase();
    }
  }
}

 console.log(newStr);

Comments

1

function convert(str, from, to) {
  const lookup = new Map(from.map((f, i) => [f, to[i]]));
  return str.replace(/./g, (letter) => {
    const lowerCased = letter.toLowerCase();
    const converted = lookup.get(lowerCased) || lowerCased;
    return letter === lowerCased ? converted : converted.toUpperCase();
  });
}

const str = "Pizza2Day!";
const originalValues = ['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'];
const encryptedValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

console.log(convert(str, originalValues, encryptedValues));

Comments

1

I know functional Javascript may sound a crazy thing but here it is:

const originalValues = ['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'];

const encryptedValues = ['m', 'h', 't', 'f', 'g', 'k', 'b', 'p', 'j', 'w', 'e', 'r', 'q', 's', 'l', 'n', 'i', 'u', 'o', 'x', 'z', 'y', 'v', 'd', 'c', 'a'];

var str = "Pizza2Day!";

let encrypt = (str) => str.split('').map((char) => char.toUpperCase() === char ? originalValues.findIndex((x) => x == char.toLowerCase()) !== -1 ? encryptedValues[originalValues.findIndex((x) => x == char.toLowerCase())].toUpperCase() : char : originalValues.findIndex((x) => x == char) !== -1 ? encryptedValues[originalValues.findIndex((x) => x == char)] : char).join('');

console.log(encrypt(str));
console.log(encrypt("Hello World!"));

Here's the algorithm:

  1. First we convert the string to an array str.split('')
  2. Then we map every char from the array .map((char) => ....
  3. We check If char is already uppercase char.toUpperCase() === char ?
    1. Then If its uppercase check if the original values contain an index for an element such as originalValues.findIndex(...) !== -1 ?
      • the element has the same value as the char converted to LowerCase (x) => x == char.toLowerCase()
    2. Then return the value at it's index in the corresponding encryptedValues converted to Upper Case encryptedValues[originalValues.findIndex((x) => x == char.toLowerCase())].toUpperCase()
    3. Else (if it's not contained) use the provided value : char
  4. Else if it's not uppercase check
    1. Then if the original values contain an index for an element such as originalValues.findIndex(...) !== -1 ?
      • the element has the same value as the char (x) => x == char
    2. Then return the value at it's index in the corresponding encryptedValues encryptedValues[originalValues.findIndex((x) => x == char)]
    3. Else return the character at the current index : char
  5. And convert the array back to string .join('')

Comments

0

Fast and easy way.

   function dict(str){
       re = /[abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ]/g;
       to = "mhtfgkbpjwerqslniuoxzyvdcaMHTFGKBPJWERQSLNIUOXZYVDCA";
    
       function replacer(chr) { return to.charAt(re.source.indexOf(chr)-1); }
       return str.replace(re,replacer);
    }
    
    console.log(dict("Pizza2Day!"));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.