Javascript reverse alphabet

Viewed 2652

so I've been messing around with the .replace() function lately and wanted to make it reverse whatever the user inputs. (Aka a -> z, A -> Z, b -> y, B -> Y, ...)

I'm using function stacking, so I just added .replace().replace()... for every letter, but of course that won't work since whenever it hits n, it will begin to reverse all the progress and I end up with an inaccurate translation. Any idea how I can work around this, since as far as I know, JS doesn't have a .reverse() function like Python?

In case you need it, here's my code

//replacing letters
lettertext = ttext.replace("a", "z")
.replace("A", "Z")
.replace("b", "y")
.replace("B", "y")
.replace("c", "x")
.replace("C", "X")
.replace("d", "w")
.replace("D", "W")
.replace("e", "v")
.replace("E", "V")
.replace("f", "u")
.replace("F", "U")
.replace("g", "t")
.replace("G", "T")
.replace("h", "s")
.replace("H", "S")
.replace("i", "r")
.replace("I", "R")
.replace("j", "q")
.replace("J", "Q")
.replace("k", "p")
.replace("K", "P")
.replace("l", "o")
.replace("L", "O")
.replace("m", "n")
.replace("M", "N")
.replace("n", "m")
.replace("N", "M")
.replace("o", "l")
.replace("O", "L")
.replace("p", "k")
.replace("P", "K")
.replace("q", "j")
.replace("Q", "J")
.replace("r", "i")
.replace("R", "I")
.replace("s", "h")
.replace("S", "H")
.replace("t", "g")
.replace("T", "G")
.replace("u", "f")
.replace("U", "F")
.replace("v", "e")
.replace("V", "E")
.replace("w", "d")
.replace("W", "D")
.replace("x", "c")
.replace("X", "C")
.replace("y", "b")
.replace("Y", "B")
.replace("z", "a")
.replace("Z", "A")
.replace("ä", "ß")
.replace("Ä", "ẞ")
.replace("ö", "ü")
.replace("Ö", "Ü")
.replace("ü", "ö")
.replace("Ü", "Ö")
.replace("ß", "ä")
.replace("ẞ", "Ä")
8 Answers

Just create an array consisting of string characters from a - z and another array consisting of all the 8 umlaut characters that you mentioned.

You can now simply create a reusable function say, reverseChar() that accepts a character as a parameter.

The function can then check if the inputted character is an alphabet or an umlaut character using a basic regex tester.

The function then tries to match the inputted character with the string characters from the respective array and if there is a match, return the same indexed character from the array reversed.


Try inputting any character from a-z, A-Z or one of the umlaut characters mentioned above in the code snippet below to see how it works:

var alpha = ["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 umlauts = ["ä","Ä","ö","Ö","ü","Ü","ß","ẞ"]

var val = "";

var result = document.getElementById("result");

function reverseChar(x) {
    
    if (/^[a-zA-Z]+$/.test(x)) {
      for (i = 0; i < 26; i++) {
          if (x.toLowerCase() == alpha[i]) {
              if (x == x.toUpperCase()) {
                val = ((alpha.reverse())[i]).toUpperCase();
              } else {
                val = (alpha.reverse())[i];
              }
          }
      }
   result.innerHTML = `The reversed character for <strong>${x}</strong> is <strong>${val}</strong>`;
    } else {
        for (i = 0; i < umlauts.length; i++) {
         if (x == umlauts[i]) {
            val = (umlauts.reverse())[i];
          }
        }
        result.innerHTML = `The reversed character for <strong>${x}</strong> is <strong>${val}</strong>`;
    }
}

// JavaScript below is for the HTML Example

var btn = document.getElementById("btn");

function checkChar(){
    var char = document.getElementById("char");
    var input = char.value;
    reverseChar(input);
}

btn.addEventListener("click", checkChar);
<input id="char" type="text" maxlength="1" />
<button type="button" id="btn">Check reversed character</button>
<p id="result"></p>

You could take a hash table for the pairs and map new character or the original character if not available in the hash table.

function replace(string) {
    var code = { "a": "z", "A": "Z", "b": "y", "B": "y", "c": "x", "C": "X", "d": "w", "D": "W", "e": "v", "E": "V", "f": "u", "F": "U", "g": "t", "G": "T", "h": "s", "H": "S", "i": "r", "I": "R", "j": "q", "J": "Q", "k": "p", "K": "P", "l": "o", "L": "O", "m": "n", "M": "N", "n": "m", "N": "M", "o": "l", "O": "L", "p": "k", "P": "K", "q": "j", "Q": "J", "r": "i", "R": "I", "s": "h", "S": "H", "t": "g", "T": "G", "u": "f", "U": "F", "v": "e", "V": "E", "w": "d", "W": "D", "x": "c", "X": "C", "y": "b", "Y": "B", "z": "a", "Z": "A", "ä": "ß", "Ä": "ẞ", "ö": "ü", "Ö": "Ü", "ü": "ö", "Ü": "Ö", "ß": "ä", "ẞ": "Ä" };
    return Array.from(string, c => code[c] || c).join('');
}

console.log(replace('Übermut2019')); // 'Öyvinfg2019'
console.log(replace('Öyvinfg2019')); // 'Übermut2019'

Create an object where key will be the letters of the string and its value will be the character which with you want to replace.

The on getting the input value split the string and create an array and use map and inside it's callback function check for the case of the character.

If it is lower case then directly retrieve the value, if upper case convert it to lower case to get the value from dictionary object and then convert it back to uppercase before returning.

Use join to create the final string

let rvObj = {
  a: 'z',
  b: 'y'
}

function reverse() {
  var b = document.getElementById("text")
    .value //get value of input
    .trim() // remove whitespace
    .split("") // create an array
    .map(function(a) { //map will return new array
      return a === a.toLowerCase() ? rvObj[a] : rvObj[a.toLowerCase()].toUpperCase();
    }).join(""); // create a string from the array
  console.log(b);
};
<input type="text" id='text'>
<button type='button' onclick='reverse()'>Reverse</button>

Replace won't work in this case because—as you already noticed—it will not track which letters have been replaced by a prior replace operation. So, a sequence of replace operations such as

//...
.replace("M", "N")
//...
.replace("N", "M")
//...

will just undo itself (if no replacement on substrings "N" takes place in the meantime).

You can however just map over the string as an array and then work on the ASCII/UTF8 encoding of the characters to reverse the alphabetic sequence.

const s = "AzByCx";

const f = (string) => Array.from(string)
  .map(c => {
      const code = c.charCodeAt(0);

      // Leave characters `c` outside the character set [a-zA-Z] unchanged.
      if (code < 0x41 || (code > 0x5A && code < 0x61) || code > 0x7A) { 
          return c;
      }
      
      // Compute offset to last character in the set [a-z] (ASCII/UTF8: 0x41-0x5A) respectively [A-Z] (ASCII/UTF8: 0x61-0x7A)
      let offset;
      let base;
      if (code <= 0x5A) {
          offset = 0x5A - code;
          base = 0x41;
      } else {
         offset = 0x7A - code;
         base = 0x61;
      }

      // Compute new character encoding and convert back to string.
      return String.fromCharCode(base + offset)
  })
  .join('');

console.log(`${s} ~> ${f(s)}`);
console.log(`${f(s)} ~> ${f(f(s))}`);

You can extend this to include Umlauts using the same approach.

You have to switch every letter only once. You can use this pattern:

a='abcxyz'.replace(/./g,function(letter){
switch (letter) {
        case 'a':
            return 'z'
    default:
        return letter
}
})

What we doing, It will replace a to z. But it will not replace it again to a. Every letter is replaced only once.

The function I used for the replace, is executed on every letter in the string.

Insted of using all the replace statments, you can use the char code, to automatically find the matching pair:

a='abcxyzABC'.replace(/./g,function(letter){
if (letter>='a' && letter<='z') {
    return String.fromCharCode( 'z'.charCodeAt(0) - letter.charCodeAt(0) + 'a'.charCodeAt(0)  )
}
if (letter>='A' && letter<='Z') {
    return String.fromCharCode( 'Z'.charCodeAt(0) - letter.charCodeAt(0) + 'A'.charCodeAt(0)  )
}
})

//ouptut: 'zyxcbaZYX"

Easiest way is to use built in functions, split, reverse, and join

function reverseString(str) {

    // Step 1. Use the split() method to return a new array ["h", "e", "l", "l", "o"]
    var splitString = str.split(""); 


    // Step 2. Use the reverse() method to reverse the new created array
    // will look like ["o", "l", "l", "e", "h"]
    var reverseArray = splitString.reverse(); 

    // Step 3. Use the join() method to join all elements of the array into a string
    // will look like "olleh"
    var joinArray = reverseArray.join(""); 


    //Step 4. Return the reversed string
    return joinArray; // "olleh"
}

reverseString("hello");

There are already a lot of answers here, but it looked fun so here is my solution explained:

  1. Split the alphabet into first part & second part
  2. Reverse the second part
  3. Check every letter in which part it is and replace it by same index but reversed of the other part
  4. Add each letter to solution

EDIT: If you want to to complete sentences, also check on space :)

var alphabet = 'abcdefghijklmnopqrstuvwxyz';
var firstpart = alphabet.substring(0,13).split('');
var secondpart = alphabet.substring(13).split('').reverse();
var button = document.getElementById("button");
var solution = '';

// Click function
button.onclick = function() {
var b = document.getElementById("text").value.split('');
// Loop every letter of input
for (var i = 0 ; i < b.length; i++) {
 if (firstpart.indexOf(b[i]) !== -1) {
   solution += secondpart[firstpart.indexOf(b[i])];
 } else {
   solution += firstpart[secondpart.indexOf(b[i])];
  }
}
console.log(solution);
// Reset solution
solution = '';
}
<input type="text" id='text'>
<button type='button'id='button'>Reverse</button>

Related