Rot-13: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Smalltalk}}: {{Lines_too_long}})
Line 1,153: Line 1,153:
'nop123'</lang>
'nop123'</lang>
=={{header|Smalltalk}}==
=={{header|Smalltalk}}==
{{Lines_too_long}}
{{works with|GNU Smalltalk}}
{{works with|GNU Smalltalk}}
Here we implemented three ways. The first one is the simplest. The second demonstrates extending the String class with a generic <code>rot</code> method, which in turn uses two ''new'' method for the class Character (+ and -). The third one is an imitation of the <tt>tr '[a-m][n-z]' '[n-z][a-m]'</tt> approach (see UNIX Shell example), done through a block closure and using also the new method <code>trFrom:to:</code> for Character.
Here we implemented three ways. The first one is the simplest. The second demonstrates extending the String class with a generic <code>rot</code> method, which in turn uses two ''new'' method for the class Character (+ and -). The third one is an imitation of the <tt>tr '[a-m][n-z]' '[n-z][a-m]'</tt> approach (see UNIX Shell example), done through a block closure and using also the new method <code>trFrom:to:</code> for Character.

Revision as of 22:31, 29 January 2010

Task
Rot-13
You are encouraged to solve this task according to the task description, using any language you may know.

Implement a "rot-13" function (or procedure, class, subroutine, or other "callable" object as appropriate to your programming environment). Optionally wrap this function in a utility program which acts like a common UNIX utility, performing a line-by-line rot-13 encoding of every line of input contained in each file listed on its command line, or (if no filenames are passed thereon) acting as a filter on its "standard input." (A number of UNIX scripting languages and utilities, such as awk and sed either default to processing files in this way or have command line switches or modules to easily implement these wrapper semantics, i.e. Perl and Python).

The "rot-13" encoding is commonly known from the early days of Usenet "Netnews" as a way of obfuscating text to prevent casual reading of spoiler or potentially offensive material. Many news reader and mail user agent programs have built-in "rot-13" encoder/decoders or have the ability to feed a message through any external utility script for performing this (or other) actions.

The definition of the rot-13 function is to simply replace every letter of the ASCII alphabet with the letter which is "rotated" 13 characters "around" the 26 letter alphabet from it's normal cardinal position (wrapping around from "z" to "a" as necessary). Thus the letters "abc" become "nop" and so on. Technically rot-13 is a "monoalphabetic substitution cipher" with a trivial "key". A proper implementation should work on upper and lower case letters, preserve case, and pass all non-alphabetic characters in the input stream through without alteration.

Ada

<lang ada>with Ada.Text_IO.Text_Streams; use Ada.Text_IO.Text_Streams; with Ada.Strings.Maps; use Ada.Strings.Maps; with Ada.Command_Line; use Ada.Command_Line;

procedure Rot_13 is

  From_Sequence : Character_Sequence := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  Result_Sequence : Character_Sequence := "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
  Rot_13_Mapping : Character_Mapping := To_Mapping(From_Sequence, Result_Sequence);
  In_Char : Character;
  Stdio : Stream_Access := Stream(Ada.Text_IO.Standard_Input);
  Stdout : Stream_Access := Stream(Ada.Text_Io.Standard_Output);
  Input : Ada.Text_Io.File_Type;

begin

  if Argument_Count > 0 then
     for I in 1..Argument_Count loop
        begin
           Ada.Text_Io.Open(File => Input, Mode => Ada.Text_Io.In_File, Name => Argument(I));
           Stdio := Stream(Input);
            while not Ada.Text_Io.End_Of_File(Input) loop
              In_Char :=Character'Input(Stdio); 
              Character'Output(Stdout, Value(Rot_13_Mapping, In_Char));
           end loop;
           Ada.Text_IO.Close(Input);
        exception
           when Ada.Text_IO.Name_Error =>
              Ada.Text_Io.Put_Line(File => Ada.Text_Io.Standard_Error, Item => "File " & Argument(I) & " is not a file.");
           when Ada.Text_Io.Status_Error =>
              Ada.Text_Io.Put_Line(File => Ada.Text_Io.Standard_Error, Item => "File " & Argument(I) & " is already opened.");
        end;
     end loop;
  else
     while not Ada.Text_Io.End_Of_File loop
        In_Char :=Character'Input(Stdio); 
        Character'Output(Stdout, Value(Rot_13_Mapping, In_Char));
     end loop;
  end if;

end Rot_13;</lang>

ALGOL 68

Translation of: Modula-3
Works with: ALGOL 68 version Standard - no extensions to language used
Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386

<lang algol68>BEGIN

 CHAR c;
 on logical file end(stand in, (REF FILE f)BOOL: (stop; SKIP));
 on line end(stand in, (REF FILE f)BOOL: (print(new line); FALSE));
 DO
   read(c);
   IF c >= "A" AND c <= "M" OR c >= "a" AND c <= "m" THEN
     c := REPR(ABS c + 13)
   ELIF c >= "N" AND c <= "Z" OR c >= "n" AND c <= "z" THEN
     c := REPR(ABS c - 13)
   FI;
   print(c)
 OD

END # rot13 #</lang> Sample run on linux:

$ echo Big fjords vex quick waltz nymph! | a68g Rot-13.a68
Ovt swbeqf irk dhvpx jnygm alzcu!

AutoHotkey

Code modified from stringmod by Hugo: ahk discussion <lang AutoHotkey>Str0=Hello, This is a sample text with 1 2 3 or other digits!@#$^&*()-_= Str1 := Rot13(Str0) Str2 := Rot13(Str1) MsgBox % Str0 "`n" Str1 "`n" Str2

Rot13(string) {

  Loop Parse, string
  {
     char := Asc(A_LoopField)
     ; o is 'A' code if it is an uppercase letter, and 'a' code if it is a lowercase letter
     o := Asc("A") * (Asc("A") <= char && char <= Asc("Z")) + Asc("a") * (Asc("a") <= char && char <= Asc("z"))
     If (o > 0)
     {
        ; Set between 0 and 25, add rotation factor, modulus alphabet size
        char := Mod(char - o + 13, 26)
        ; Transform back to char, upper or lower
        char := Chr(char + o)
     }
     Else
     {
        ; Non alphabetic, unchanged
        char := A_LoopField
     }
     rStr .= char
  }
  Return rStr

}</lang>

AWK

<lang awk>BEGIN {

 for(i=0; i < 256; i++) {
   amap[sprintf("%c", i)] = i
 }
 for(l=amap["a"]; l <= amap["z"]; l++) {
   rot13[l] = sprintf("%c", (((l-amap["a"])+13) % 26 ) + amap["a"])
 }
 FS = ""

} {

 o = ""
 for(i=1; i <= NF; i++) {
   if ( amap[tolower($i)] in rot13 ) {
     c = rot13[amap[tolower($i)]]
     if ( tolower($i) != $i ) c = toupper(c)
     o = o c
   } else {
     o = o $i
   }
 }
 print o

}</lang>

BASIC

Works with: QuickBasic version 4.5

<lang qbasic>CLS INPUT "Enter a string: ", s$ ans$ = "" FOR a = 1 TO LEN(s$)

       letter$ = MID$(s$, a, 1)
       IF letter$ >= "A" AND letter$ <= "Z" THEN
               char$ = CHR$(ASC(letter$) + 13)
               IF char$ > "Z" THEN char$ = CHR$(ASC(char$) - 26)
       ELSEIF letter$ >= "a" AND letter$ <= "z" THEN
               char$ = CHR$(ASC(letter$) + 13)
               IF char$ > "z" THEN char$ = CHR$(ASC(char$) - 26)
       ELSE
               char$ = letter$
       END IF
       ans$ = ans$ + char$

NEXT a PRINT ans$</lang>

Befunge

<lang befunge>~:"z"`#v_:"m"`#v_:"`"` |>

:"Z"`#v_:"M"`#v_:"@"`|>
: 0 `#v_@v-6-7<      >

, < <+6+7 <<v</lang>

C

<lang c>#include<stdio.h>

  1. include<stdlib.h>
  2. include<ctype.h>
  1. define MAXLINE 1024

char *rot13(char *s) {

       char *p=s;
       int upper;
       while(*p) {
               upper=toupper(*p);
               if(upper>='A' && upper<='M') *p+=13;
               else if(upper>='N' && upper<='Z') *p-=13;
               ++p;
       }
       }
       return s;

}

void rot13file(FILE *fp) {

       static char line[MAXLINE];
       while(fgets(line, MAXLINE, fp)>0) fputs(rot13(line), stdout);

}

int main(int argc, char *argv[]) {

       int n;
       FILE *fp;
       if(argc>1) {
               for(n=1; n<argc; ++n) {
                       if(!(fp=fopen(argv[n], "r"))) {
                               fprintf(stderr, "ERROR: Couldn\'t read %s\n", argv[n]);
                               exit(EXIT_FAILURE);
                       }
                       rot13file(fp);
                       fclose(fp);
               }
       } else rot13file(stdin);
       return EXIT_SUCCESS;

}</lang>

C++

<lang cpp>#include <iostream>

  1. include <istream>
  2. include <ostream>
  3. include <fstream>
  4. include <cstdlib>
  5. include <string>

// the rot13 function std::string rot13(std::string s) {

 static std::string const
   lcalph = "abcdefghijklmnopqrstuvwxyz",
   ucalph = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 std::string result;
 std::string::size_type pos;
 result.reserve(s.length());
 for (std::string::iterator it = s.begin(); it != s.end(); ++it)
 {
   if ( (pos = lcalph.find(*it)) != std::string::npos )
     result.push_back(lcalph[(pos+13) % 26]);
   else if ( (pos = ucalph.find(*it)) != std::string::npos )
     result.push_back(ucalph[(pos+13) % 26]);
   else
     result.push_back(*it);
 }
 return result;

}

// function to output the rot13 of a file on std::cout // returns false if an error occurred processing the file, true otherwise // on entry, the argument is must be open for reading int rot13_stream(std::istream& is) {

 std::string line;
 while (std::getline(is, line))
 {
   if (!(std::cout << rot13(line) << "\n"))
     return false;
 }
 return is.eof();

}

// the main program int main(int argc, char* argv[]) {

 if (argc == 1) // no arguments given
   return rot13_stream(std::cin)? EXIT_SUCCESS : EXIT_FAILURE;
 std::ifstream file;
 for (int i = 1; i < argc; ++i)
 {
   file.open(argv[i], std::ios::in);
   if (!file)
   {
     std::cerr << argv[0] << ": could not open for reading: " << argv[i] << "\n";
     return EXIT_FAILURE;
   }
   if (!rot13_stream(file))
   {
     if (file.eof())
       // no error occurred for file, so the error must have been in output
       std::cerr << argv[0] << ": error writing to stdout\n";
     else
       std::cerr << argv[0] << ": error reading from " << argv[i] << "\n";
     return EXIT_FAILURE;
   }
   file.clear();
   file.close();
   if (!file)
     std::cerr << argv[0] << ": warning: closing failed for " << argv[i] << "\n";
 }
 return EXIT_SUCCESS;

}</lang>

C#

<lang csharp>using System; using System.Text;

class Program {

   static string rot13(string text) {
       StringBuilder outp = new StringBuilder();
       foreach (char i in text) {
           if (i >= 'a' && i <= 'm' || i >= 'A' && i <= 'M') outp.Append((char)((int)i + 13));         
           else if (i >= 'n' && i <= 'z' || i >= 'N' && i <= 'Z') outp.Append((char)((int)i - 13));
           else outp.Append(i);
       }
       return outp.ToString();
   }
   static void Main(string[] args) {
       Console.WriteLine(rot13("nowhere ABJURER")); //Example
   }

}</lang>

Clojure

<lang lisp>(defn rot-13 [c]

 (let [i (int c)]
   (cond
     (or (and (>= i (int \a)) (<= i (int \m)))
         (and (>= i (int \A)) (<= i (int \M))))
       (char (+ i 13))
     (or (and (>= i (int \n)) (<= i (int \z)))
         (and (>= i (int \N)) (<= i (int \Z))))
       (char (- i 13))
     :else c)))

(apply str (map rot-13 "abcxyzABCXYZ")) ;; output "nopklmNOPKLM"</lang> An alternative implementation using a closure or two: <lang lisp>(let [A (into #{} "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")

     A-map (zipmap A (take 52 (drop 26 (cycle A))))]     
 
 (defn rot13[in-str]
   (reduce str (map #(if (A %1) (A-map %1) %1)  in-str))))

(rot13 "The Quick Brown Fox Jumped Over The Lazy Dog!") ;; produces "Gur Dhvpx Oebja Sbk Whzcrq Bire Gur Ynml Qbt!"</lang>

Common Lisp

The standard gives implementations great leeway with respect to character encodings, so we can't rely on the convenient properties of ASCII. <lang lisp>(defconstant +alphabet+ '(#\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))

(defun rot13 (s)

 (map 'string
   (lambda (c &aux (n (position (char-upcase c) +alphabet+)))
     (if n
       (funcall
         (if (lower-case-p c) #'char-downcase #'identity)
         (nth (mod (+ 13 n) 26) +alphabet+))
       c))
   s))</lang>

D

Implement a Rot-13 function. <lang d>module rot13 ; import std.stdio ;

version(D_Version2) {

 import std.algorithm ;

}

char rot13char(char t) {

 ubyte c = (t & 0x9f) - 1 ;
 if (c > 25 || (t & 0x40) == 0 )
   return t ;
 c = (c + 13) % 26 ; // that's why Rot-13 :)
 return (t & 0x60) | (c + 1) ;   

}

string rot13(string s) {

 string t ;
 foreach(c ; s)
   t ~= rot13char(c) ;
 return t ;

}

void main(string[] args) {

 string text = "abc! ABC!" ;
 writefln(rot13(text)) ;
 writefln(rot13("abcdefghijklmnopqrstuvwxyz"~
                "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) ;

version(D_Version2) {

 writefln(map!(rot13char)(text)) ; 
 writefln(map!(rot13char)("abcdefghijklmnopqrstuvwxyz"~ 
                          "ABCDEFGHIJKLMNOPQRSTUVWXYZ")) ;

} }</lang>

A simpler version (D V.1): <lang d>import std.stdio, std.string; void main() {

   auto r13 = letters.maketrans(uppercase[13..$] ~ uppercase[0..13] ~
                                lowercase[13..$] ~ lowercase[0..13]);
   writefln("This is the 1st test!".translate(r13, null));

}</lang>

E

<lang e>pragma.enable("accumulator")

var rot13Map := [].asMap() for a in ['a', 'A'] {

   for i in 0..!26 {
       rot13Map with= (a + i, E.toString(a + (i + 13) % 26))
   }

}

def rot13(s :String) {

 return accum "" for c in s { _ + rot13Map.fetch(c, fn{ c }) }

}</lang>

Erlang

<lang erlang>rot13(Str) ->

   F = fun(C) when (C >= $A andalso C =< $M); (C >= $a andalso C =< $m) -> C + 13;
          (C) when (C >= $N andalso C =< $Z); (C >= $n andalso C =< $z) -> C - 13;
          (C) -> C
       end,
   lists:map(F, Str).</lang>

F#

Illustrates turning a string into an array of chars then composition of type casting with a conversion function. We create a composite that converts its input to an integer, calls the convertion function and then casts to a char type. The result is an array of modified chars that we can use to create a new string. <lang fsharp>let rot13 (s : string) =

  let rot c =
      match c with
      | c when c > 64 && c < 91 -> ((c - 65 + 13) % 26) + 65
      | c when c > 96 && c < 123 -> ((c - 97 + 13) % 26) + 97
      | _ -> c
  s |> Array.of_seq
  |> Array.map(int >> rot >> char)
  |> (fun seq -> new string(seq))</lang>

FALSE

<lang false>[^$1+][$32|$$'z>'a@>|$[\%]?~[13\'m>[_]?+]?,]#%</lang>

Forth

A simple version, using nested conditionals. <lang forth>: r13 ( c -- o )

 dup 32 or                                    \ tolower
 dup [char] a [char] z 1+ within if
   [char] m > if -13 else 13 then +
 else drop then ;</lang>

A table driven version which should be more efficient. The mechanism is flexible enough to express any sort of transform. <lang forth>: ,chars ( end start -- )

 do i c, loop ;
xlate create does> ( c -- c' ) + c@ ;

xlate rot13

 char A         0    ,chars
 char Z 1+ char N    ,chars
 char N    char A    ,chars
 char a    char Z 1+ ,chars
 char z 1+ char n    ,chars
 char n    char a    ,chars
 256       char z 1+ ,chars
rot13-string ( addr len -- )
 over + swap do i c@ rot13 i c! loop ;
.rot13" ( string -- )
 [char] " parse 2dup rot13-string type ;

.rot13" abjurer NOWHERE" \ nowhere ABJURER</lang>

Fortran

Works with: Fortran version 90 and later

<lang fortran>MODULE ROT13

 IMPLICIT NONE
 CHARACTER(80) :: teststr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ - abcdefghijklmnopqrstuvwxyz"
 CONTAINS
 SUBROUTINE ROT_13(s)
   CHARACTER(*), INTENT(in out) :: s
   INTEGER :: i
   DO i = 1, LEN(s)
      SELECT CASE (s(i:i))
        CASE ("A":"M")
          s(i:i) = ACHAR(IACHAR(s(i:i))+13)
        
        CASE ("N":"Z")
          s(i:i) = ACHAR(IACHAR(s(i:i))-13)
        
        CASE ("a":"m")
          s(i:i) = ACHAR(IACHAR(s(i:i))+13)
        
        CASE ("n":"z")
          s(i:i) = ACHAR(IACHAR(s(i:i))-13)
      END SELECT
   END DO
 END SUBROUTINE ROT_13

END MODULE ROT13

PROGRAM Example

 USE ROT13

 CALL ROT_13(teststr)
 WRITE(*,*) teststr
 CALL ROT_13(teststr)
 WRITE(*,*) teststr

END PROGRAM Example</lang>

Output

NOPQRSTUVWXYZABCDEFGHIJKLM - nopqrstuvwxyzabcdefghijklm
ABCDEFGHIJKLMNOPQRSTUVWXYZ - abcdefghijklmnopqrstuvwxyz

Groovy

Solution: <lang groovy>def rot13 = { String s ->

   (s as List).collect { ch ->
       switch (ch) {
           case ('a'..'m') + ('A'..'M'):
               return (((ch as char) + 13) as char)
           case ('n'..'z') + ('N'..'Z'):
               return (((ch as char) - 13) as char)
           default:
               return ch
       }
   }.inject ("") { string, ch -> string += ch}

}</lang>

Test program: <lang groovy>println rot13("Noyr jnf V, 'rer V fnj Ryon.")</lang>

Output:

Able was I, 'ere I saw Elba.

Haskell

Straightforward implementation by checking multiple cases:

<lang haskell>import Data.Char

rot13 :: Char -> Char rot13 c

 | toLower c >= 'a' && toLower c <= 'm' = chr (ord c + 13)
 | toLower c >= 'n' && toLower c <= 'z' = chr (ord c - 13)
 | otherwise = c</lang>

To wrap that as an utility program, here's a quick implementation of a general framework:

<lang haskell>import System.Environment import System.IO import System.Directory import Control.Monad

hInteract :: (String -> String) -> Handle -> Handle -> IO () hInteract f hIn hOut =

 hGetContents hIn >>= hPutStr hOut . f

processByTemp :: (Handle -> Handle -> IO ()) -> String -> IO () processByTemp f name = do

 hIn <- openFile name ReadMode
 let tmp = name ++ "$" 
 hOut <- openFile tmp WriteMode
 f hIn hOut
 hClose hIn
 hClose hOut
 removeFile name
 renameFile tmp name

process :: (Handle -> Handle -> IO ()) -> [String] -> IO () process f [] = f stdin stdout process f ns = mapM_ (processByTemp f) ns</lang>

Then the wrapped program is simply <lang haskell>main = do

names <- getArgs
process (hInteract (map rot13)) names</lang>

Note that the framework will read the file lazily, which also provides buffering.

Icon

like javascript <lang icon>procedure main()

  local str, plain, rot13
  rot13 := "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM";
  plain := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  str := "ABJURER nowhere"
  write(map(str, plain, rot13))

end</lang>

J

<lang j>rot13=: {&( (65 97+/~i.26) 13&|.@[} i.256 )&.(a.&i.)</lang>

For example:

   rot13 'abc! ABC!'
nop! NOP!

Compare with the solution to the Change String Case task.

Java

<lang java>import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; public class ROT13{

      public static void main(String[] args){
              BufferedReader in;
              if(args.length >= 1){
                      for(String file: args){
                              try{
                                      in= new BufferedReader(new FileReader(file));
                                      String line;
                                      while((line= in.readLine()) != null){
                                              System.out.println(convert(line));
                                      }
                              }catch(FileNotFoundException e){
                                      e.printStackTrace();
                              }catch(IOException e){
                                      e.printStackTrace();
                              }
                      }
              }else{
                      try{
                              in= new BufferedReader(new InputStreamReader(System.in));
                              String line;
                              while((line= in.readLine()) != null){
                                      System.out.println(convert(line));
                              }
                      }catch(IOException e){
                              e.printStackTrace();
                      }
              }
      }
      public static String convert(String msg){
              String retVal= "";
              for(char a: msg.toCharArray()){
                      if(a >= 'A' && a <= 'Z'){
                              a+= 13;
                              if(a > 'Z') a-= 26;
                      }else if(a >= 'a' && a <= 'z'){
                              a+= 13;
                              if(a > 'z') a-= 26;
                      }
                      retVal+= a;
              }
              return retVal;
      }

}</lang>

JavaScript

<lang javascript>var rot13Str = "nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM"; var plainStr = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";

function rot13(s) {

 var a = [];
 for (var i=0; i<s.length; i++) {
   var c = s.charAt(i);
   var found = plainStr.indexOf(c);
   a.push(found<0 ? c : rot13Str.charAt(found));
 }
 return a.join('');

}

alert( rot13("ABJURER nowhere") ); // NOWHERE abjurer</lang>

<lang logo>to rot13 :c

 make "a difference ascii lowercase :c  ascii "a
 if or :a < 0 :a > 25 [output :c]
 make "delta ifelse :a < 13 [13] [-13]
 output char sum :delta ascii :c

end

print map "rot13 "|abjurer NOWHERE| nowhere ABJURER</lang>

Lua

<lang lua>function rot(l, o) return (l < 26 and l > -1) and string.char((l+13)%26 + o) end a, A = string.byte'a', string.byte'A' val = io.read() val = val:gsub("(.)", function(l) return rot(l:byte()-a,a) or rot(l:byte()-A,A) or l end) print(val)</lang>

Mathematica

<lang Mathematica>charslower="abcdefghijklmnopqrstuvwxyz"//Characters; charsupper="ABCDEFGHIJKLMNOPQRSTUVWXYZ"//Characters; ruleslower=Rule@@@({charslower,RotateLeft[charslower,13]} // Transpose); rulesupper=Rule@@@({charsupper,RotateLeft[charsupper,13]} // Transpose); rules=Join[ruleslower,rulesupper]; text="Hello World! Are you there!?" text=StringReplace[text,rules] text=StringReplace[text,rules]</lang> gives back: <lang Mathematica>Hello World! Are you there!? Uryyb Jbeyq! Ner lbh gurer!? Hello World! Are you there!?</lang>

MMIX

<lang mmix>// main registers p IS $255 % text pointer c GREG % char cc GREG % uppercase copy of c u GREG % all purpose

LOC Data_Segment GREG @ Test BYTE "dit is een bericht voor de keizer",#a,0

LOC #100 Main LDA p,Test TRAP 0,Fputs,StdOut % show text to encrypt LDA p,Test % points to text to encrypt JMP 4F // do in place text encryption % REPEAT 2H ADD cc,c,0 % copy char SUB cc,cc,' ' % make uppercase CMP u,cc,'A' BN u,3F % IF c < 'A' OR c > 'Z' THEN next char CMP u,cc,'Z' BP u,3F CMP u,cc,'N' % ELSE BN u,1F % IF c < 'N' THEN encrypt 'up' SUB c,c,26 % ELSE char ready for encrypt 'down' 1H INCL c,13 % encrypt char STBU c,p % replace char with encrypted char 3H INCL p,1 % move to next char 4H LDBU c,p % get next char PBNZ c,2B % UNTIL EOT // print result LDA p,Test TRAP 0,Fputs,StdOut % show encrypted text TRAP 0,Halt,0</lang> Example:

~/MIX/MMIX/Progs> mmix rot13simpl
dit is een bericht voor de keizer
qvg vf rra orevpug ibbe qr xrvmre

Modula-3

This implementation reads from stdin and writes to stdout. <lang modula3>MODULE Rot13 EXPORTS Main;

IMPORT Stdio, Rd, Wr;

VAR c: CHAR;

<*FATAL ANY*>

BEGIN

 WHILE NOT Rd.EOF(Stdio.stdin) DO
   c := Rd.GetChar(Stdio.stdin);
   IF c >= 'A' AND c <= 'M' OR c >= 'a' AND c <= 'm' THEN
     c := VAL(ORD((ORD(c) + 13)), CHAR);
   ELSIF c >= 'N' AND c <= 'Z' OR c >= 'n' AND c <= 'z' THEN
     c := VAL(ORD((ORD(c) - 13)), CHAR);
   END;
   Wr.PutChar(Stdio.stdout, c);
 END;

END Rot13.</lang>

Output:

martin@thinkpad:~$ ./prog
Foo bar baz
Sbb one onm
martin@thinkpad:~$ echo "Bar baz foo" | ./prog
One onm sbb
martin@thinkpad:~$ echo "Foo bar baz" > foo.txt 
martin@thinkpad:~$ echo "quux zeepf" >> foo.txt 
martin@thinkpad:~$ cat foo.txt | ./prog
Sbb one onm
dhhk mrrcs

OCaml

Straightforward implementation for characters by using character range patterns: <lang ocaml>let rot13 c = match c with

  'A'..'M'
| 'a'..'m' -> char_of_int (int_of_char c + 13)
| 'N'..'Z'
| 'n'..'z' -> char_of_int (int_of_char c - 13)
| _        -> c</lang>

We provide a function for converting whole strings: <lang ocaml>let rot13_str s =

 let len = String.length s in
 let result = String.create len in
 for i = 0 to len - 1 do
   result.[i] <- rot13 s.[i]
 done;
 result</lang>

Oz

<lang oz>declare

 fun {RotChar C}
    if     C >= &A andthen C =< &Z then &A + (C - &A + 13) mod 26
    elseif C >= &a andthen C =< &z then &a + (C - &a + 13) mod 26
    else C
    end
 end
 fun {Rot13 S}
    {Map S RotChar}
 end

in

 {System.showInfo {Rot13 "NOWHERE Abjurer 42"}}
 {System.showInfo {Rot13 {Rot13 "NOWHERE Abjurer 42"}}}</lang>

Perl

<lang perl>sub rot13 {

 my $string = shift;
 $string =~ tr/A-Za-z/N-ZA-Mn-za-m/;
 return $string;

}

print rot13($_) while (<>);</lang>

Input:

NOWHERE Abjurer

Output:

ABJURER Nowhere

This one-liner version demonstrates that most of the verbosity above was simply needed to define a function:

<lang perl>perl -pe 'tr/A-Za-z/N-ZA-Mn-za-m/'</lang>

Perl 6

Works with: Rakudo version #22 "Thousand Oaks"

<lang perl6>sub rot13 ($s) { $s.trans('A..Za..z' => 'N..ZA..Mn..za..m') }

sub MAIN (*@files) {

    print rot13 do @files
      ?? [~] map { slurp $_ }, @files
      !! $*IN.slurp;

}</lang>

PHP

PHP has a built-in function for this: <lang php>echo str_rot13('foo'), "\n";</lang> will output

sbb

Here is an implementation: <lang php><?php function rot13($s) {

   return strtr($s, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
                    'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm');

}

echo rot13('foo'), "\n"; ?></lang>

Output:

sbb

Pike

<lang pike> import Crypto;

int main(){

  string r = rot13("Hello, World");
  write(r + "\n");

} </lang>

Pop11

In Pop11 characters are just integers, so we can use integer comparisons and arithmetic (assuming ASCII based encoding).

<lang pop11>define rot13(s);

   lvars j, c;
   for j from 1 to length(s) do
       s(j) -> c;
       if `A` <= c and c <= `M` or `a` <= c and c <= `m` then
           c + 13 -> s(j);
       elseif `N` <= c and c <= `Z` or `n` <= c and c <= `z` then
           c - 13 -> s(j);
       endif;
   endfor;
   s;

enddefine;

rot13('NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm') =></lang>

Python

Python 2.x (but not 3.x) has built-in rot13 encoding and decoding:

Works with: Python version 2.x
>>> u'foo'.encode('rot13')
'sbb'
>>> 'sbb'.decode('rot13')
u'foo'

Here is an implementation:

Works with: Python version 2.x

<lang python>#!/usr/bin/env python import string def rot13(s):

  """Implement the rot-13 encoding function: "rotate" each letter by the
     letter that's 13 steps from it (wrapping from z to a)
  """
  return s.translate(
      string.maketrans(
          string.ascii_uppercase + string.ascii_lowercase,
          string.ascii_uppercase[13:] + string.ascii_uppercase[:13] +
          string.ascii_lowercase[13:] + string.ascii_lowercase[:13]
          )
      )

if __name__ == "__main__":

  """Peform line-by-line rot-13 encoding on any files listed on our
     command line or act as a standard UNIX filter (if no arguments
     specified).
  """
  import fileinput
  for line in fileinput.input():
     print rot13(line),  # (Note the trailing comma; avoid double-spacing our output)!</lang>

The str.translate() and string.maketrans() functions make the function's definition almost trivial. It's a one-line function with some line wrapping for legibility. The fileinput module similarly makes the wrapper functionality trivial to implement. (This implementation is about seven logical lines long).

Works with: Python version 3.x

<lang python>#!/usr/bin/env python import string def rot13(s):

  """Implement the rot-13 encoding function: "rotate" each letter by the
     letter that's 13 steps from it (wrapping from z to a)
  """
  return s.translate(
      str.maketrans(
          string.ascii_uppercase + string.ascii_lowercase,
          string.ascii_uppercase[13:] + string.ascii_uppercase[:13] +
          string.ascii_lowercase[13:] + string.ascii_lowercase[:13]
          )
      )

if __name__ == "__main__":

  """Peform line-by-line rot-13 encoding on any files listed on our
     command line or act as a standard UNIX filter (if no arguments
     specified).
  """
  import fileinput
  for line in fileinput.input():
     print(rot13(line), end="")</lang>

R

<lang R>rot13 <- function(x) {

 old <- paste(letters, LETTERS, collapse="", sep="")
 new <- paste(substr(old, 27, 52), substr(old, 1, 26), sep="")
 chartr(old, new, x)

} x <- "The Quick Brown Fox Jumps Over The Lazy Dog!.,:;'#~[]{}" rot13(x) # "Gur Dhvpx Oebja Sbk Whzcf Bire Gur Ynml Qbt!.,:;'#~[]{}" x2 <- paste(letters, LETTERS, collapse="", sep="") rot13(x2) # "nNoOpPqQrRsStTuUvVwWxXyYzZaAbBcCdDeEfFgGhHiIjJkKlLmM"</lang> For a slightly more general function, see the example on the chartr help page.

REBOL

<lang REBOL>REBOL [

   Title: "Rot-13"
   Date: 2009-12-14
   Author: oofoe
   URL: http://rosettacode.org/wiki/Rot-13

]

Test data has upper and lower case characters as well as characters
that should not be transformed, like numbers, spaces and symbols.

text: "This is a 28-character test!"

print "Using cipher table:"

I build a set of correspondence lists here. 'x' is the letters from
A-Z, in both upper and lowercase form. Note that REBOL can iterate
directly over the alphabetic character sequence in the for loop. 'y'
is the cipher form, 'x' rotated by 26 characters (remember, I have
the lower and uppercase forms together). 'r' holds the final result,
built as I iterate across the 'text' string. I search for the
current character in the plaintext list ('x'), if I find it, I get
the corresponding character from the ciphertext list
('y'). Otherwise, I pass the character through untransformed, then
return the final string.

rot-13: func [ "Encrypt or decrypt rot-13 with tables." text [string!] "Text to en/decrypt." /local x y r i c ] [ x: copy "" for i #"a" #"z" 1 [append x rejoin [i uppercase i]] y: rejoin [copy skip x 26 copy/part x 26] r: copy ""

repeat i text [append r either c: find/case x i [y/(index? c)][i]] r ]

Note that I am setting the 'text' variable to the result of rot-13
so I can reuse it again on the next call. The rot-13 algorithm is
reversible, so I can just run it again without modification to decrypt.

print [" Encrypted:" text: rot-13 text] print [" Decrypted:" text: rot-13 text]


print "Using parse:"

clamp: func [ "Contain a value within two enclosing values. Wraps if necessary." x v y ][ x: to-integer x v: to-integer v y: to-integer y case [v < x [y - v] v > y [v - y + x - 1] true v] ]

I'm using REBOL's 'parse' word here. I set up character sets for
upper and lower-case letters, then let parse walk across the
text. It looks for matches to upper-case letters, then lower-case,
then skips to the next one if it can't find either. If a matching
character is found, it's mathematically incremented by 13 and
clamped to the appropriate character range. parse changes the
character in place in the string, hence this is a destructive
operation.

rot-13: func [ "Encrypt or decrypt rot-13 with parse." text [string!] "Text to en/decrypt. Note: Destructive!" ] [ u: charset [#"A" - #"Z"] l: charset [#"a" - #"z"]

parse text [some [ i:  ; Current position. u (i/1: to-char clamp #"A" i/1 + 13 #"Z") | ; Upper case. l (i/1: to-char clamp #"a" i/1 + 13 #"z") | ; Lower case. skip]]  ; Ignore others. text ]

As you see, I don't need to re-assign 'text' anymore.

print [" Encrypted:" rot-13 text] print [" Decrypted:" rot-13 text] </lang>

Output:

Using cipher table:
    Encrypted: Guvf vf n 28-punenpgre grfg!
    Decrypted: This is a 28-character test!
Using parse:
    Encrypted: Guvf vf n 28-punenpgre grfg!
    Decrypted: This is a 28-character test!

Ruby

<lang ruby>def rot13(s)

 s.tr('A-Za-z', 'N-ZA-Mn-za-m')

end

alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; puts rot13(alpha)</lang>

Output:

NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm

Scala

<lang scala>scala> def rot13(s: String) = s map {

    |   case c if 'a' <= c.toLower && c.toLower <= 'm' => c + 13 toChar
    |   case c if 'n' <= c.toLower && c.toLower <= 'z' => c - 13 toChar
    |   case c => c
    | }

rot13: (s: String)String

scala> rot13("7 Cities of Gold.") res61: String = 7 Pvgvrf bs Tbyq.

scala> rot13(res61) res62: String = 7 Cities of Gold.</lang>

Scheme

Library: SRFI-13
Works with: Chicken Scheme

<lang scheme>(use srfi-13)

(define (rot13 str)

 (define (rot13-char c)
   (string (integer->char

(cond ((or (and (char>=? c #\a) (char<? c #\n))

                       (and (char>=? c #\A) (char<? c #\N)))

(+ (char->integer c) 13)) ((or (and (char>=? c #\n) (char<? c #\{))

                       (and (char>=? c #\N) (char<? c #\[)))

(- (char->integer c) 13))

                  (else (char->integer c))))))
 
 (if (= (string-length str) 0)
     (newline)
     (begin
       (display (rot13-char (car (string->list str)))) 
       (rot13 (list->string (cdr (string->list str)))))))</lang>

Seed7

This rot13 program reads from standard input and writes to standard output: <lang seed7>$ include "seed7_05.s7i";

const proc: main is func

 local
   var char: ch is ' ';
 begin
   ch := getc(IN);
   while not eof(IN) do
     if (ch >= 'a' and ch <= 'm') or (ch >= 'A' and ch <= 'M') then
       ch := chr(ord(ch) + 13);
     elsif (ch >= 'n' and ch <= 'z') or (ch >= 'N' and ch <= 'Z') then
       ch := chr(ord(ch) - 13);
     end if;
     write(ch);
     ch := getc(IN);
   end while;
 end func;</lang>

Slate

A shell script:

<lang slate>#!/usr/local/bin/slate

ch@(String Character traits) rot13 [| value upper |

 upper: ch isUppercase.
 value: (ch toLowercase as: Integer).
 (value >= 97) /\ (value < 110)
   ifTrue: [value: value + 13]
   ifFalse: [(value > 109) /\ (value <= 122)
               ifTrue: [value: value - 13]].
 upper
   ifTrue: [(value as: String Character) toUppercase]
   ifFalse: [value as: String Character]

].

lobby define: #Rot13Encoder &parents: {Encoder}.

c@(Rot13Encoder traits) convert [

 [c in isAtEnd] whileFalse: [c out nextPut: c in next rot13].

].

(Rot13Encoder newFrom: Console reader to: Console writer) convert.</lang>

Normal functions:

<lang slate>ch@(String Character traits) rot13 [| value upper |

 upper: ch isUppercase.
 value: (ch toLowercase as: Integer).
 (value >= 97) /\ (value < 110)
   ifTrue: [value: value + 13]
   ifFalse: [(value > 109) /\ (value <= 122)
               ifTrue: [value: value - 13]].
 upper
   ifTrue: [(value as: String Character) toUppercase]
   ifFalse: [value as: String Character]

].

s@(String traits) rot13 [| result |

 result: s newSameSize.
 s doWithIndex: [| :each :index |
   result at: index put: each rot13].
 result

].

slate[37]> 'abc123' rot13. 'nop123'</lang>

Smalltalk

Some lines in this example are too long (more than 80 characters). Please fix the code if it's possible and remove this message.
Works with: GNU Smalltalk

Here we implemented three ways. The first one is the simplest. The second demonstrates extending the String class with a generic rot method, which in turn uses two new method for the class Character (+ and -). The third one is an imitation of the tr '[a-m][n-z]' '[n-z][a-m]' approach (see UNIX Shell example), done through a block closure and using also the new method trFrom:to: for Character.

<lang smalltalk>"1. simple approach" rot13 := [ :string |

   string collect: [ :each | | index |
       index := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' indexOf: each ifAbsent: [ 0 ]. "Smalltalk uses 1-based indexing"
       index isZero 
           ifTrue: [ each ] 
           ifFalse: [ 'nopqrstuvwxyzabcdefghijklmNOPQRSTUVWXYZABCDEFGHIJKLM' at: index ] ] ].

(rot13 value: 'Test123') printNl "gives 'Grfg123'"


"2. extending built-in classes" Character extend [

 + inc [
    (inc isKindOf: Character)
    ifTrue: [
       ^ ( Character value: ((self asInteger) + (inc asInteger)) )
    ] ifFalse: [
      ^ ( Character value: ((self asInteger) + inc) )
    ]
 ]
 - inc [
   ^ ( self + (inc asInteger negated) )
 ]
 trFrom: map1 to: map2 [
    (map1 includes: self) ifTrue: [
       ^ map2 at: (map1 indexOf: self)
    ] ifFalse: [ ^self ]
 ]

].

String extend [

 rot: num [ |s|
   s := String new.
   self do: [ :c |
        ((c asLowercase) between: $a and: $z)

ifTrue: [ |c1|

             c1 := ( $a + ((((c asLowercase) - $a + num) asInteger) rem:26)).
             (c isLowercase) ifFalse: [ c1 := c1 asUppercase ].
             s := s, (c1 asString)
          ]
          ifFalse: [

s := s, (c asString)

          ]
    ].
    ^s
 ]

].

('abcdefghijklmnopqrstuvwxyz123!' rot: 13) displayNl. (('abcdefghijklmnopqrstuvwxyz123!' rot: 13) rot: 13) displayNl.


"2. using a 'translation'. Not very idiomatic Smalltalk code" rotThirteen := [ :s | |m1 m2 r|

 r := String new.
 m1 := OrderedCollection new.
 0 to: 25 do: [ :i | m1 add: ($a + i) ].
 m2 := OrderedCollection new.
 0 to: 25 do: [ :i | m2 add: ($a + ((i+13) rem: 26)) ].
 s do: [ :c |
   (c between: $a and: $z) | (c between: $A and: $Z)
     ifTrue: [ | a |
       a := (c asLowercase) trFrom: m1 to: m2.
       (c isUppercase) ifTrue: [ a := a asUppercase ].
       r := r, (a asString)] 
     ifFalse: [ r := r, (c asString) ]
 ].
 r

].

(rotThirteen value: 'abcdefghijklmnopqrstuvwxyz123!') displayNl.</lang>

Tcl

<lang tcl>proc rot13 line {

   string map {
       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
       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
       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
   } $line

}</lang>

Using

Library: TclX

we can write

<lang tcl>package require Tclx proc rot13 str {

   translit "A-Za-z" "N-ZA-Mn-za-m" $str

}</lang>

TI-83 BASIC

Calculator symbol translations:

"STO" arrow: →

Perfoms ROT-13 on the contents of Str1. Also uses the string variables Str0 and Str2 and the real variable N.

<lang ti83b>:"ABCDEFGHIJKLMNOPQRSTUVWXYZ→Str0

"."→Str2
For(N,1,length(Str1
If inString(Str0,sub(Str1,N,1
Then
inString(Str0,sub(Str1,N,1
Ans+13-26(Ans>13
Str2+sub(Str0,Ans,1→Str2
Else
Str2+sub(Str1,N,1→Str2
End
End
sub(Str2,2,length(Str2)-1→Str1</lang>

UNIX Shell

Bourne Shell

<lang bash>#!/bin/sh function rot13 () {

  tr '[a-m][n-z][A-M][N-Z]' '[n-z][a-m][N-Z][A-M]'
  }

[ "$#" -lt 1 ] && {

  rot13
  } || for eachFile in "$@"; do
           cat "$eachFile" | rot13
           done</lang>

UNIX shell assumes availability of the standard UNIX utility commands (in the "coreutils" package on Linux systems, for example); thus the tr (translate) command is trivially provided with the proper arguments to perform the rotations. This example shows proper quoting around "$@" (magical argument list) and "$eachFile" such that this script work properly even if some of the files named on the command line contain embedded spaces or other such characters.

Ursala

I/O in Ursala is meant to be handled automatically as much as possible by the run time system. This source text describes only a function that operates on the contents of a list of files passed to it as an argument, with the transformed files returned as a result. The #executable compiler directive and its parameters mean that this source will be compiled to an executable file with the required command line interface. The rot13 encryption algorithm itself is a simple finite map implemented in a half line of code. <lang Ursala>#import std

  1. executable (<'parameterized','default-to-stdin'>,<>)

rot = ~command.files; * contents:= ~contents; * * -:~& -- ^p(~&,rep13~&zyC)~~ ~=`A-~ letters</lang>

Vedit macro language

Using ROT13.TBL from here <lang vedit>Translate_Load("ROT13.TBL") Translate_Block(0, File_Size)</lang>

You can execute the macro from DOS command prompt with the following command:

vpw -q -x rot13.vdm inputfile -a outputfile

In addition to translating a block of text, the translate table allows viewing and editing ROT-13 text without translating the actual file into ASCII. The displayed characters and keyboard input are translated on-the-fly. This is the normal way to edit for example DOS/OEM and EBCDIC files.

Visual Basic .NET

Platform: .NET

Works with: Visual Basic .NET version 9.0+

<lang vbnet>Module Module1

  Private Function rot13(ByVal str As String) As String
      Dim newChars As Char(), i, j As Integer, original, replacement As String
      original = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
      replacement = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
      newChars = str.ToCharArray()
      For i = 0 To newChars.Length - 1
          For j = 0 To 51
              If newChars(i) = original(j) Then
                  newChars(i) = replacement(j)
                  Exit For
              End If
          Next
      Next
      Return New String(newChars)
  End Function

End Module</lang> This solution just uses simple textual substitution, since the number of characters involved is small. If the cipher involved more characters, it would be better to use character arithmetic; however, this is not encouraged in VB.Net.

XSLT

Textual transforms are one of the domains XSLT was designed for. <lang xml><xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

 <xsl:output method="text" />
 <xsl:variable name="alpha">ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz</xsl:variable>
 <xsl:variable name="rot13">NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm</xsl:variable>  
 <xsl:template match="body"> 
   <xsl:apply-templates/>
 </xsl:template>
 <xsl:template match="rot13">
   <xsl:value-of select="translate(.,$alpha,$rot13)"/>
 </xsl:template>

</xsl:stylesheet></lang> This will transform the input:

<body>The <rot13>Abjurer</rot13> was to be found <rot13>Nowhere</rot13>.</body>

into:

The Nowhere was to be found Abjurer.