39
\$\begingroup\$

Task

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).

Examples

Input
Output

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
\$\endgroup\$
13
  • 3
    \$\begingroup\$ The problem shouldn't be a tag, so I removed ROT13, just an FYI \$\endgroup\$ Jan 27 '11 at 21:18
  • 3
    \$\begingroup\$ Don't you mean A-Za-z (to count both upper- and lower-case) ? \$\endgroup\$
    – Joey Adams
    Jan 27 '11 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
    Jan 30 '11 at 18:59
  • 19
    \$\begingroup\$ Saying xor is not encryption is like saying a+b is not math. \$\endgroup\$
    – Nakilon
    Jan 30 '11 at 19:02
  • 3
    \$\begingroup\$ Tags are used to categorize questions and help search similar questions. The cryptography tag (from Greek kryptós, "hidden, secret"; and graphein, "writing") in particular is for encryption and decryption problems. All encryption and decryption, not only those that are secure for modern applications. \$\endgroup\$
    – Angs
    Dec 3 '16 at 10:33

59 Answers 59

1
2
1
\$\begingroup\$

K, 31

{x^(,/{x!(13_x),13#x}'.Q`A`a)x}
\$\endgroup\$
2
  • \$\begingroup\$ {x^a(,/-13 13#\:a:.Q.A)?x} for 26 bytes \$\endgroup\$
    – mkst
    Jan 31 '18 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
    Dec 8 '20 at 15:41
1
\$\begingroup\$

Tcl, 74 chars

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

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)}))
\$\endgroup\$
2
  • \$\begingroup\$ Invalid because the interpreter is not available. \$\endgroup\$
    – cat
    Feb 22 '16 at 21:29
  • \$\begingroup\$ @cat Somehow I got the url wrong. It is fixed now. \$\endgroup\$ Feb 23 '16 at 23:24
1
\$\begingroup\$

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])
\$\endgroup\$
1
\$\begingroup\$

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!
            Console.WriteLine(f("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,./"));
// NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm1234567890,./
        }
    }
}
\$\endgroup\$
1
\$\begingroup\$

Befunge-93, 72 67 bytes

Edit: -5 bytes thanks to James Holderness

<,<v!:+*"a"*`"`"\`\"{":\*"G"*`"@"\`\"[":::_@#+1:~
+0|_\"N"%6-55*1+%

Try it online!

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

\$\endgroup\$
0
1
\$\begingroup\$

Retina, 13 bytes

13+T`zlZL`l_L

Try it online!

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

Explanation

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.

\$\endgroup\$
1
\$\begingroup\$

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+$_)})

}

@(

,("Hello!","Uryyb!")
,("HELLO","URYYB")
,("URYYB","HELLO")
,("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz","NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm")
,("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"
}

Output:

True: Uryyb!
True: URYYB
True: HELLO
True: NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
True: Jul qvq gur puvpxra pebff gur ebnq?
To get to the other side!
\$\endgroup\$
1
\$\begingroup\$

naz, 176 bytes

2a2x1v6a8m2x2v9a4a2x3v9a5a2x4v5a2x5v9a4a2x6v9a5a2x7v1x1f1r3x1v7e3x5v5g3x2v2g8f0x1x2f3x4v3l8f0x1x3f3x3v4g9a4a8f0x1x4f9s4s8f0x1x5f3x7v6l8f0x1x6f3x6v4g9a4a8f0x1x7f0a0x1x8f1o1f0x1f

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
\$\endgroup\$
1
\$\begingroup\$

Vyxal, 10 bytes

kB½(nn13ǓĿ

Try it Online!

-4 thx to lyxal

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

JavaScript (Node.js), 65 bytes

o=>(b=Buffer)(b(o).map(c=>c%32<26&c>64?(c%32+13)%26+c-c%32:c))+''

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
\$\endgroup\$
0
\$\begingroup\$

Scala 108

def m(a:Int,z:Int,c:Int)=if(c>=a&&c<z)a+((c-a+13)%26)else c
"Ok?".map(c=>print(m(65,91,m(97,123,c)).toChar))

ungolfed:

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))

result:

Bx?
\$\endgroup\$
0
\$\begingroup\$

Mathematica 102

StringReplace[Input[],
Join@@Table[Rule@@FromCharacterCode/@{i+c,Mod[i+13,26]+c},{c,{65,97}},{i,0,25}]]
\$\endgroup\$
0
\$\begingroup\$

JavaScript 135

s=prompt(),o='',i=0
while((c=s.charCodeAt(i++)))c+=c>64&&c<91?c<52?13:-13:c>96&&c<123?c<109?13:-13:0,o+=String.fromCharCode(c)
alert(o)
\$\endgroup\$
0
\$\begingroup\$

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)
\$\endgroup\$
0
\$\begingroup\$

Scala (96 chars)

def r(s:String)=s.map{c⇒val m = if(c<91)65 else 97
if(c.isLetter)
((c+13-m)%26+m).toChar
else c}
\$\endgroup\$
0
\$\begingroup\$

J, 32 29 bytes

a.{~3&u:+13*2|&.>:'@MZ`mz'&I.

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Python 3, 70 bytes

a=input()
for i in a:print(end=i.isalpha()*chr(65+(ord(i)-52)%26)or i)
\$\endgroup\$
1
  • 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\$ Feb 27 '19 at 18:17
0
\$\begingroup\$

Japt, 28 bytes

c_d)è"%l")?Z|H)<#n?Z+D:Z-D:Z

Try it!

c_d)è"%l")?Z|H)<#n?Z+D:Z-D:Z
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
\$\endgroup\$
5
  • \$\begingroup\$ 20 bytes using replace and switching to v2.0a1. There must be a shorter way, though. \$\endgroup\$
    – Shaggy
    Feb 27 '19 at 17:42
  • \$\begingroup\$ 18 bytes \$\endgroup\$
    – Shaggy
    Feb 27 '19 at 17:45
  • \$\begingroup\$ Nice - I had not tried the beta version yet. Looks like regex may have improved? \$\endgroup\$
    – dana
    Feb 27 '19 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
    Feb 27 '19 at 17:50
  • \$\begingroup\$ 17 bytes. \$\endgroup\$
    – Shaggy
    Feb 27 '19 at 17:50
0
\$\begingroup\$

PHP - 27 Bytes

<?=str_rot13(fgets(STDIN));
\$\endgroup\$
0
\$\begingroup\$

T-SQL, 80 bytes

The TRANSLATE function was introduced in SQL Server 2017.

Input is taken from the column I of the table T.

SELECT TRANSLATE(I,A+B,B+A)FROM(VALUES('ABCDEFGHIJKLM','NOPQRSTUVWXYZ'))V(A,B),T

SQL Fiddle

\$\endgroup\$
0
\$\begingroup\$

Zsh, 126 .. 102 bytes

Shell builtins only. Rotates any letter in A-Za-z, using decimal-ascii conversion. Try it Online!

r()printf ${(#)$((13+$1+(##$X-$1)%26))}
for X (${(s::)1})case $X {[A-Z])r 52;;[a-z])r 84;;*)printf $X}

Previously: 126bytes 112bytes 106bytes
Initial (wrong) solutions: 56bytes 83bytes

\$\endgroup\$
0
\$\begingroup\$

Google Sheets, 144

  • Input: A1 (Given named range "A", +1 score)
  • Column B: =ArrayFormula(CODE(MID(A,SEQUENCE(LEN(A)),1, given named range "B", +1 score
  • Final output: =ArrayFormula(JOIN(,IF(B=0,,CHAR(IF((B>64)*(B<91),B+13*-1^(B>77),IF((B<97)+(B>122),B,B+13*-1^(B>109
\$\endgroup\$
0
\$\begingroup\$

Jelly, 12 bytes

ØAṙ13,µ;Œlyɠ

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
\$\endgroup\$
0
\$\begingroup\$

Haskell, 77 bytes

r(a:b:c)=[a..b]++r c
main=interact$map$(r"\0@NZAM[`nzam{\1114111"!!).fromEnum

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Stax, 2 bytes

:3

Run and debug it

:3

\$\endgroup\$
0
\$\begingroup\$

GNU AWK, 147 8+82 = 90 bytes

-lordchr argument

BEGIN{RS=".|";ORS=e}$0=RT~/[A-Za-z]/?chr(ord(RT)+(ord(tolower(RT))>109?-13:13)):RT

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.

\$\endgroup\$
0
\$\begingroup\$

Ly, 65 bytes

ir[:'@Gf(123)Lf'ZGf'aLfp*!**[p'ZGsp(13)+'Z(32)l*+G[p(26)-0]p0]po]

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.

   :'@Gf(123)Lf'ZGf'aLfp*!**

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.

                              'ZGsp

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.

                                   (13)+'Z(32)l*+

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

                                                 G[p(26)-0]p

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

\$\endgroup\$
0
\$\begingroup\$

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 stars)
1A 13 47 CB AF D6 41 38
0E FE 1A 30 0A FE 0D 78
38 02 D6 1A C6 0D 47 *70
23 04 10* E4 C9

Disassembly and explanation:

rot13:
    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     if borrowed, wasn't letter
    cp 26           ; FE 1A     is it 26 or more now?
    jr nc,put       ; 30 0A     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     if carry, was greater than 13
    sub 26          ; D6 1A     subtract 26 if was greater
notsub:
    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
#else
    ld (hl),b       ; 70        store
    inc hl          ; 23        and increment
    inc b           ; 04        if b was 0, it's now 1
    djnz rot13      ; 10 E4     jump back if b is 1 (and decrement)
#endif
    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.

\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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