Read a string of characters and produce the ROT13 of it. All characters besides [a-zA-Z] should be output verbatim. Each letter in the output may be in any case you wish (you do not have to preserve it).

ROT13 is a simple substitution cipher where each letter of the alphabet is rotated by 13 places (it doesn't matter whether you do it forward or backward, since ROT13 is it's own inverse).



Hello, world!
Uryyb, jbeyq!

Code Golf and Coding Challenges is awesome.
Pbqr Tbys naq Pbqvat Punyyratrf vf njrfbzr.

Mod abuse!1!!1
Zbq nohfr!1!!1
  • 3
    \$\begingroup\$ The problem shouldn't be a tag, so I removed ROT13, just an FYI \$\endgroup\$ Commented Jan 27, 2011 at 21:18
  • 3
    \$\begingroup\$ Don't you mean A-Za-z (to count both upper- and lower-case) ? \$\endgroup\$
    – Joey Adams
    Commented Jan 27, 2011 at 21:33
  • 6
    \$\begingroup\$ @Chris Jester-Young, it belongs to this category at wikipedia. It's part of cryptography, just not the hardest one. Anyway, I'm not longer following this site. Community dissapointed me. Sorry. GL HF. \$\endgroup\$
    – Nakilon
    Commented Jan 30, 2011 at 18:59
  • 21
    \$\begingroup\$ Saying xor is not encryption is like saying a+b is not math. \$\endgroup\$
    – Nakilon
    Commented Jan 30, 2011 at 19:02
  • 3
    \$\begingroup\$ @Nakilon: Actually, I call that arithmetic, not mathematics. *shrug* \$\endgroup\$ Commented Jan 30, 2011 at 19:04

69 Answers 69


Julia 1.0, 69 bytes


Try it online!


Most of the code is an anonymous function that takes an integer codepoint and prints the corresponding ROT-13'd character:


x->(                                                )  # Anonymous function of x
    c=Char(x);                                         # Cast x to Char and save as c
                    c+                                 # Start with c and add to its codepoint:
                      isletter(c)*                     # If c is not a letter, the rest of this is
                                                       # multiplied by 0
                                  13*(-1)^(       )    # 13, times +/- 1 according to:
                                           x&31>13     # Low 5 bits of x are greater than 13
                                                       # I.e. x > 'M' (if x is uppercase) or x > 'm'
                                                       # (if x is lowercase)
              print(                               )   # Output the resulting character

We then apply this function, vectorized, to the array of (integer) codepoints returned by read(stdin).

  • \$\begingroup\$ 65 bytes \$\endgroup\$
    – H.PWiz
    Commented Jan 2, 2019 at 13:19

JavaScript (Node.js), 65 bytes


Try it online!

o=>(                    // Define a function taking o and r
  b = Buffer            // Assign b to Buffer
)(                      // And call on...
  b(o).map(c=>          // a Buffer of the charcodes of o, mapped to...
    c%32<26&c>64        // If the character is alphabetical - charcode%32 is less than 26, charcode is >64
      ?                 // Then
    (c%32+13)%26+c-c%32 // Rot-13 the character - Mod 32, add 13, mod 26, add correct number depending on whether it's uppercase of lowercase.
    :c)                 // Else return the original string
 ) + ''                 // Coerce to string

Atto-8 Machine Code, 23 bytes

Decoded as hex:

E8 00 E0 C0 20 A0 61 84 00 0D 85 0D 90 0D 85 F2 90 D0 80 00 E1 01 E3

Commented disassembly listing:

# Generated by Dasm

  nop @dyn        # padding for alignment
  x00 lda         # read from standard input
  ld0 x20 orr     # clone and convert to lowercase
  x61 sub         # map lowercase alphabet to 0-25
  x00             # default offset is 0
  x0D su2 x0D iff # if between a-m, offset is 13
  x0D su2 xF2 iff # if between n-z, offset is -13
  st0 add         # add offset to original input
  x00 sta         # write to standard output
  x01 sti         # loop back to start

K, 31

  • \$\begingroup\$ {x^a(,/-13 13#\:a:.Q.A)?x} for 26 bytes \$\endgroup\$
    – mkst
    Commented Jan 31, 2018 at 21:31
  • \$\begingroup\$ Assuming only rot13'ing upper case letters is acceptable, {x^a(,/|0 13_a:.Q.A)?x} for 23 bytes. Handling both upper and lower case can be done in 29 by swapping the inner lambda in @tmartin's answer for {x!,/|0 13_x}. \$\endgroup\$
    – coltim
    Commented Dec 8, 2020 at 15:41

Tcl, 74 chars

package require [set c tcl::transform::rot];$c 13 stdin;fcopy stdin stdout

Haskell (103)

Reused maybe c id $ lookup c from jloy's answer.

main=interact$map(\c->maybe c id$lookup c$[['a'..'z'],['A'..'Z']]>>=zip<*>uncurry(flip(++)).splitAt 13)

pyg-i - 76 Bytes

P(STDI.read().t({a:a-13 if(77<a<91)or a>109 else a+13 for a in M(ord,STl)}))

Python Equivient:

import sys,string
print(sys.stdin.read().translate({a:a-13 if(77<a<91)or a>109 else a+13 for a in map(ord,string.ascii_letters)}))
  • \$\begingroup\$ Invalid because the interpreter is not available. \$\endgroup\$
    – cat
    Commented Feb 22, 2016 at 21:29
  • \$\begingroup\$ @cat Somehow I got the url wrong. It is fixed now. \$\endgroup\$ Commented Feb 23, 2016 at 23:24

Python: 60 bytes

lambda s:''.join([chr((ord(c.lower())-84)%26+97)for c in s])

The only thing I don't like is having that .lower() in there. Any suggestions?

edit: I can get rid of the .lower(), and handle capitals better, but it's 94 bytes now:

lambda s:''.join([chr((ord(c)-(52if ord(c)<97else 84))%26+(65if ord(c)<97else 97))for c in s])

C#, 94 bytes

s=>{var r="";foreach(var c in s)r+=(char)(Char.IsLetter(c)?(c|32)<110?c+13:c-13:c);return r;};

Anonymous function which returns the string of characters rotated by 13 places, based on this C answer from Fors. Works for any lower or upper letters while keeping other input the same.

Full program with ungolfed method and test cases:

using System;

namespace ROT13
    class Program
        static void Main(string[] args)
            Func<string, string> f =
            s =>
                var r = "";
                foreach (var c in s)
                    r += (char)(Char.IsLetter(c) ? (c | 32) < 110 ? c + 13 : c - 13 : c);
                return r;

            Console.WriteLine(f("TOO MANY SECRETS!"));   // GBB ZNAL FRPERGF!
            Console.WriteLine(f("too many secrets!"));   // gbb znal frpergf!
            Console.WriteLine(f("gbb znal frpergf!"));   // too many secrets!
// NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm1234567890,./

Befunge-93, 72 67 bytes

Edit: -5 bytes thanks to James Holderness


Try it online!

Kinda disappointed in the previous Befunge answers, so I wrote one with much less whitespace.


Retina, 13 bytes


Try it online!

The straightforward transliteration that directly applies ROT13 would be 2 bytes longer Try it online!


The transliteration stage here is wrapped in a loop stage making it run 13 times (or until the string is not transformed anymore, which can only happen if the input string has no alphabetic characters).

In the transliteration, characters in zlZL are transformed into the characters at the same positions in l_L. Here, z and Z are exactly what they look like, while l and L get converted into the lowercase and uppercase alphabets. The final letters of those alphabets are ignored because they already appear earlier in the string, and _ is just a placeholder to make the uppercase alphabet line up correctly. The result is transforming each letter into the next one (a->b,b->c,...,z->a); doing this 13 times is ROT13.


Powershell, 77 bytes

-join($args|% t*y|%{[char]((("$_"-match'[a-m]')-("$_"-match'[n-z]'))*13+$_)})

Test script:

$f = {

-join($args|% t*y|%{[char]((("$_"-match'[a-m]')-("$_"-match'[n-z]'))*13+$_)})



,("Why did the chicken cross the road?
Gb trg gb gur bgure fvqr!",
"Jul qvq gur puvpxra pebff gur ebnq?
To get to the other side!")

) | % {
    $s,$expected = $_
    $result = &$f $s
    "$($result-eq$expected): $result"


True: Uryyb!
True: NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
True: Jul qvq gur puvpxra pebff gur ebnq?
To get to the other side!

Python 3, 70 bytes

for i in a:print(end=i.isalpha()*chr(65+(ord(i)-52)%26)or i)
  • 2
    \$\begingroup\$ Your proposed solution does not work with lowercase letters. It's not explicitely specified in the challenge though, so I'm not sure if your answer is valid. \$\endgroup\$ Commented Feb 27, 2019 at 18:17

PHP - 27 Bytes


naz, 176 bytes


The most involved naz solution I've written so far. This program subtracts 13 from every letter in standard input that's greater than M, and adds 13 to every other letter - whether lowercase or uppercase.

It does use a lot of logic to determine what's a letter or not, so I wouldn't be surprised if this could be improved upon.

Works for any input string terminated with the control character STX (U+0002).

Explanation (with 0x commands removed)

2a2x1v                     # Set variable 1 equal to 2
6a8m2x2v                   # Set variable 2 equal to 64 ("@")
9a4a2x3v                   # Set variable 3 equal to 77 ("M")
9a5a2x4v                   # Set variable 4 equal to 91 ("[")
5a2x5v                     # Set variable 5 equal to 96 ("`")
9a4a2x6v                   # Set variable 6 equal to 109 ("m")
9a5a2x7v                   # Set variable 7 equal to 123 ("{")
1x1f                       # Function 1
    1r                     # Read a byte of input
      3x1v7e               # Jump to function 7 if it equals variable 1
            3x5v5g         # Jump to function 5 if it's greater than variable 5
                  3x2v2g   # Jump to function 2 if it's greater than variable 2
                        8f # Otherwise, jump to function 8
1x2f                       # Function 2
    3x4v3l                 # Jump to function 3 if the register is less than variable 4
          8f               # Otherwise, jump to function 8
1x3f                       # Function 3
    3x3v4g                 # Jump to function 4 if the register is greater than variable 3
          9a4a             # Otherwise, add 13 to the register,
              8f           # then jump to function 8
1x4f                       # Function 4
    9s4s8f                 # Subtract 13 from the register, then jump to function 8
1x5f                       # Function 5
    3x7v6l                 # Jump to function 6 if the register is less than variable 7
          8f               # Otherwise, jump to function 8
1x6f                       # Function 6
    3x6v4g                 # Jump to function 4 if the register is greater than variable 6
          9a4a             # Otherwise, add 13 to the register,
              8f           # then jump to function 8
1x7f                       # Function 7
    0a                     # Add 0 to the register
1x8f                       # Function 8
    1o1f                   # Output, then jump to function 1
1f                         # Call function 1

Jelly, 12 bytes


Try it online!

This takes input from STDIN

How it works

ØAṙ13,µ;Œlyɠ - Main link. Takes no arguments
ØA           - "ABC...XYZ"
  ṙ13        - Rotate 13 steps to the left
     ,       - Pair with the unaltered alphabet
      µ      - Begin a new link with ['NOP...KLM', 'ABC...XYZ'] as argument
        Œl   - Lowercase; ['nop...klm', 'abc..xyz']
       ;     - Concatenate; ['NOP...KLM', 'ABC...XYZ', 'nop...klm', 'abc..xyz']    
           ɠ - Read a line from STDIN
          y  - Transliterate

Vyxal, 10 bytes


Try it Online!

-4 thx to lyxal

  • \$\begingroup\$ Try it Online! for 11 bytes. \$\endgroup\$
    – lyxal
    Commented May 31, 2021 at 12:47
  • \$\begingroup\$ @lyxal Thanks, next learn to count! \$\endgroup\$
    – emanresu A
    Commented May 31, 2021 at 20:11

GNU AWK, 147 8+82 = 90 bytes

-lordchr argument


Try it online!

After some thought, I realized it is possible to explore GNU AWK's ordchr extension to return the ASCII value of a character, saving tons of bytes. The ROT13 algorithm identifies if the letter is in the first or second half of the alphabet, adding of subtracting 13 to its ASCII value, accordingly.

This code transforms every character as Record Separator, then substitutes every $0 (formerly null) for the matching record separator (RT): ROT13 modified, if it's a letter; or itself, if not.


Ly, 65 bytes


Try it online!

I'm enjoying learning Ly, so even though this is an old challenge I decided to give it a shot...

This is pretty brute force and the result isn't short compared to other entries. But it does show how to do things like if-then conditional blocks in Ly, so maybe someone will find it useful?

This bit reads in a line of input as codepoints, reverses the stack, then loops through each character/codepoint. At the end of the loop the character is printed, rot13'd or not.

ir[                                                            o]

The first thing to do is duplicate the character with : since we need to do two operations and it's easier to make a copy of the character on the stack now and then do the first one. That first test checks to see if the current character is in "a-z" or "A-Z". It does that by stacking the results from 4 comparisons, >=A >Z >=a and >z. Then it combines those 0|1 results mathematically to figure out if we're in the right range.


Then the pattern I've found works for if-then is used to conditionally apply the rot-13 logic only when we get an alphabetic character. That pattern is ...test...[p...then-code...0]p. So in this case that's these bits.

                            [p                              0]p

And the code to apply the rotation starts by figuring out and remembering if the character is uppercase or not. After the s command, the backup cell will be 1|0 to indicated whether or not the character is uppercase.


After that, the code adds 13 to the codepoint, then constructs what the max codepoint value is. It's either Z or z depending on the case of the original character. The l command pushed the backup cell (upper/lower flag) onto the stack so we use that to switch the Z to z if necessary.


Once that max codepoint is on the stack the code conditionally subtracts 26 if the rotated number it too high.


At that point, the character we want to print is on top of the stack.


SM83/Z80, 29 bytes

Input string at (de), output to (hl).

  • SM83 version
1A 13 47 CB AF D6 41 38
0E FE 1A 30 0A FE 0D 78
38 02 D6 1A C6 0D 47 78
22 B7 20 E4 C9
  • Z80 version (changes in »German guillemets« except for second bytes of jr for same effective offset¹)
1A 13 47 CB AF D6 41 38
10 FE 1A 30 0C FE 0D 78
38 04 D6 1A C6 0D 47»70
23 04 10«E6 C9

Disassembly and explanation:

    ld a,(de)       ; 1A        load character
    inc de          ; 13        increment
    ld b,a          ; 47        save copy
    res 5,a         ; CB AF     clear fifth bit
    sub 65          ; D6 41     subtract 'A'
    jr c,put        ; 38 0E/10  if borrowed, wasn't letter
    cp 26           ; FE 1A     is it 26 or more now?
    jr nc,put       ; 30 0A/0C  if didn't borrow, wasn't letter
    cp 13           ; FE 0D     compare against 13
    ld a,b          ; 78        load original
    jr c,notsub     ; 38 02/04  if carry, was greater than 13
    sub 26          ; D6 1A     subtract 26 if was greater
    add 13          ; C6 0D     add 13 either way
    ld b,a          ; 47        store into b
put:                ;           b now contains rot13 version
#ifdef SM83
    ld a,b          ; 78        move into a
    ld (hl+),a      ; 22        store and increment
    or a            ; B7        test if zero
    jr nz,rot13     ; 20 E4     if not, loop
    ld (hl),b       ; 70        store
    inc hl          ; 23        and increment
    inc b           ; 04        if b was 0, it's now 1
    djnz rot13      ; 10 E6     jump back if b is 1 (and decrement)
    ret             ; C9        return

It's a bit interesting that both CPUs have a way of saving a byte that the other doesn't. The SM83 has autoincrement addressing, while the Z80 has a way to jump if b is 1.

¹ Apparently Z80 relative jump instructions are measured from the start, while SM83's are from the end. (So 18 00 is an infinite loop for Z80 and a three-cycle two-byte no-op for SM83.)


Alice, 129 bytes

 a    > Ko= h-A'.<
 #  >@o Ko<>.'Zh-=oK
>wI.=>.'a-h=oK Ko<
 *  >^#va2++3a-a'<
 6    +*   >.'zh-=oK

Try it online!


v                      >oK
    >@     >.'Zh-=oK   >'A-a3++2a*6+%'A+oK
    >^     >.'zh-=oK

Python 3, 60 bytes

import this
print("".join(this.d.get(c,c)for c in input()))

K (ngn/k), 40 bytes


Try it online!


JavaScript ES6 (155 bytes)

Here is a Caesar cipher that preserves case in in ES6.

// 155 bytes

// Begin unit tests
const { expect } = chai
const testCases = [{
  input: "Hello, world!",
  output: "Uryyb, jbeyq!",
}, {
  input: "Code Golf and Coding Challenges is awesome.",
  output: "Pbqr Tbys naq Pbqvat Punyyratrf vf njrfbzr.",
}, {
  input: "Mod abuse!1!!1",
  output: "Zbq nohfr!1!!1",
describe('Caesar cipher (ROT13)', () => {
    it('are all equal', () => {
    for (let { input, output } of testCases) {
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/3.4.1/chai.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/2.3.4/mocha.js"></script>
<div id="mocha"></div>

Here is one that is 187 bytes (+32 bytes), but no code duplication:


At 192 bytes (+37 bytes), this one is a bit larger, but it builds a lookup and does regex replace:


Scala 108

def m(a:Int,z:Int,c:Int)=if(c>=a&&c<z)a+((c-a+13)%26)else c


def m (a: Int, z:Int, c:Int) = if (c >= a && c <= z) a+((c-a+13)%26) else c
"Ok?".foreach (c => print (m ('A', 'Z', m ('a', 'z', c)).toChar))



Mathematica 102


JavaScript 135


Scala (96 chars)

def r(s:String)=s.map{c⇒val m = if(c<91)65 else 97
else c}

J, 32 29 bytes


Try it online!


Japt, 28 bytes


Try it!

c_                                # map input string through a function
  d)è"%l")?                       # regex check if current character is a letter
           Z|H)<#n?               # is it less than the letter n?
                   Z+D:           # if yes, then add 13
                       Z-D:       # otherwise, subtract 13
                           Z      # not a letter, do not transform
  • \$\begingroup\$ 20 bytes using replace and switching to v2.0a1. There must be a shorter way, though. \$\endgroup\$
    – Shaggy
    Commented Feb 27, 2019 at 17:42
  • \$\begingroup\$ 18 bytes \$\endgroup\$
    – Shaggy
    Commented Feb 27, 2019 at 17:45
  • \$\begingroup\$ Nice - I had not tried the beta version yet. Looks like regex may have improved? \$\endgroup\$
    – dana
    Commented Feb 27, 2019 at 17:47
  • \$\begingroup\$ Yeah, but it's bugged to hell at the moment - only single character class work; anything wrapped in / won't. \$\endgroup\$
    – Shaggy
    Commented Feb 27, 2019 at 17:50
  • \$\begingroup\$ 17 bytes. \$\endgroup\$
    – Shaggy
    Commented Feb 27, 2019 at 17:50

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.