Rot-13
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, e.g., Perl and Python).
![Task](http://static.miraheze.org/rosettacodewiki/thumb/b/ba/Rcode-button-task-crushed.png/64px-Rcode-button-task-crushed.png)
You are encouraged to solve this task according to the task description, using any language you may know.
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 its 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.
6502 Assembly
Written for the BeebAsm assembler, which uses '&' to indicate a hexadecimal number. Call with the address of a zero terminated string in X and Y. On exit X is preserved, Y is the length of the string and A is zero.
<lang 6502asm> buffer = &70 ; or anywhere in zero page that's good
org &1900 .rot13
stx buffer sty buffer+1 ldy #0
.loop lda (buffer),y
bne decode ; quit on ASCII 0 rts
.decode cmp #&7b ; high range
bcs next cmp #&41 ; low range bcc next cmp #&4f bcc add13 cmp #&5b bcc sub13 cmp #&61 bcc next cmp #&6f bcc add13 bcs sub13 ; saves a byte over a jump
.next iny
jmp loop
.add13 adc #13 ; we only get here via bcc; so clc not needed
jmp storeit
.sub13 sec
sbc #13
.storeit sta (buffer),y
jmp next</lang>
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
<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!
AppleScript
Using do shell script <lang Applescript>to rot13(textString) do shell script "tr a-zA-Z n-za-mN-ZA-M <<<" & quoted form of textString end rot13</lang> Pure AppleScript solution <lang Applescript>to rot13(textString)
local outChars set outChars to {} repeat with ch in (characters of textString) if (ch >= "a" and ch <= "m") or (ch >= "A" and ch <= "M") then set ch to character id (id of ch + 13) else if (ch >= "n" and ch <= "z") or (ch >= "N" and ch <= "Z") then set ch to character id (id of ch - 13) end set end of outChars to ch end return outChars as text
end rot13 </lang> Demo code: <lang AppleScript>rot13("nowhere ABJURER")</lang> Output:
abjurer NOWHERE
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
<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>
BBC BASIC
<lang bbcbasic> REPEAT
INPUT A$ PRINT FNrot13(A$) UNTIL FALSE END DEF FNrot13(A$) LOCAL A%,B$,C$ IF A$="" THEN ="" FOR A%=1 TO LEN A$ C$=MID$(A$,A%,1) IF C$<"A" OR (C$>"Z" AND C$<"a") OR C$>"z" THEN B$=B$+C$ ELSE IF (ASC(C$) AND &DF)<ASC("N") THEN B$=B$+CHR$(ASC(C$)+13) ELSE B$=B$+CHR$(ASC(C$)-13) ENDIF ENDIF NEXT A% =B$
</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>
- include<stdlib.h>
- include<ctype.h>
- 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 csharp>using System; using System.IO; using System.Linq; using System.Text;
class Program {
static char Rot13(char c) { if ('a' <= c && c <= 'm' || 'A' <= c && c <= 'M') { return (char)(c + 13); } if ('n' <= c && c <= 'z' || 'N' <= c && c <= 'Z') { return (char)(c - 13); } return c; }
static string Rot13(string s) { return new StringBuilder().Append(s.Select(Rot13).ToArray()).ToString(); }
static void Main(string[] args) { foreach (var file in args.Where(file => File.Exists(file))) { Console.WriteLine(Rot13(File.ReadAllText(file))); } if (!args.Any()) { Console.WriteLine(Rot13(Console.In.ReadToEnd())); } }
}</lang>
C++
<lang cpp>#include <iostream>
- include <istream>
- include <ostream>
- include <fstream>
- include <cstdlib>
- 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>
Here is an other approach which can rotate by any number:
<lang cpp>#include <iostream>
- include <string>
- include <boost/iostreams/concepts.hpp> // output_filter
- include <boost/iostreams/operations.hpp> // put
- include <boost/iostreams/filtering_stream.hpp>
- include <fstream>
namespace io = boost::iostreams;
class rot_output_filter : public io::output_filter { public:
explicit rot_output_filter(int r=13):rotby(r),negrot(alphlen-r){};
template<typename Sink> bool put(Sink& dest, int c){ char uc = toupper(c);
if(('A' <= uc) && (uc <= ('Z'-rotby))) c = c + rotby; else if ((('Z'-rotby) <= uc) && (uc <= 'Z')) c = c - negrot; return boost::iostreams::put(dest, c); };
private:
static const int alphlen = 26; const int rotby; const int negrot;
};
int main(int argc, char *argv[]) {
io::filtering_ostream out; out.push(rot_output_filter(13)); out.push(std::cout);
if (argc == 1) out << std::cin.rdbuf(); else for(int i = 1; i < argc; ++i){ std::ifstream in(argv[i]); out << in.rdbuf(); }
}
</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
Using Standard Functions
<lang d>import std.stdio; import std.ascii: letters, U = uppercase, L = lowercase; import std.string: maketrans, translate;
immutable r13 = maketrans(letters,
//U[13 .. $] ~ U[0 .. 13] ~ U[13 .. U.length] ~ U[0 .. 13] ~ L[13 .. L.length] ~ L[0 .. 13]);
void main() {
writeln("This is the 1st test!".translate(r13, null));
}</lang> Output:
The Quick Brown Fox Jumps Over The Lazy Dog!
Imperative Implementation
<lang d>import std.stdio, std.traits, std.ascii, std.range, std.conv;
S rot(S)(in S s, in int key) if (isSomeString!S) {
auto r = new dchar[s.walkLength];
foreach (i, const dchar c; s) { if (c.isLower()) r[i] = ((c - 'a' + key) % 26 + 'a'); else if (c.isUpper()) r[i] = ((c - 'A' + key) % 26 + 'A'); else r[i] = c; }
return to!S(r);
}
S rot13(S)(in S s) if (isSomeString!S) {
return rot(s, 13);
}
void main() {
"Gur Dhvpx Oebja Sbk Whzcf Bire Gur Ynml Qbt!".rot13().writeln();
}</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>
Euphoria
<lang Euphoria> include std/types.e include std/text.e
atom FALSE = 0 atom TRUE = not FALSE
function Rot13( object oStuff ) integer iOffset integer bIsUpper object oResult sequence sAlphabet = "abcdefghijklmnopqrstuvwxyz" if sequence(oStuff) then oResult = repeat( 0, length( oStuff ) ) for i = 1 to length( oStuff ) do oResult[ i ] = Rot13( oStuff[ i ] ) end for else bIsUpper = FALSE if t_upper( oStuff ) then bIsUpper = TRUE oStuff = lower( oStuff ) end if iOffset = find( oStuff, sAlphabet ) if iOffset != 0 then iOffset += 13 iOffset = remainder( iOffset, 26 ) if iOffset = 0 then iOffset = 1 end if oResult = sAlphabet[iOffset] if bIsUpper then oResult = upper(oResult) end if else oResult = oStuff --sprintf( "%s", oStuff ) end if end if return oResult end function
puts( 1, Rot13( "abjurer NOWHERE." ) & "\n" ) </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>
Factor
<lang factor>#! /usr/bin/env factor
USING: kernel io ascii math combinators sequences ; IN: rot13
- rot-base ( ch ch -- ch ) [ - 13 + 26 mod ] keep + ;
- rot13-ch ( ch -- ch )
{ { [ dup letter? ] [ CHAR: a rot-base ] } { [ dup LETTER? ] [ CHAR: A rot-base ] } [ ] } cond ;
- rot13 ( str -- str ) [ rot13-ch ] map ;
- main ( -- )
[ readln dup ] [ rot13 print flush ] while drop ;
MAIN: main</lang>
FALSE
<lang false>[^$1+][$32|$$'z>'a@>|$[\%]?~[13\'m>[_]?+]?,]#%</lang>
Fantom
<lang fantom> class Rot13 {
static Str rot13 (Str input) { Str result := "" input.each |Int c| { if ((c.lower >= 'a') && (c.lower <= 'm')) result += (c+13).toChar else if ((c.lower >= 'n') && (c.lower <= 'z')) result += (c-13).toChar else result += c.toChar } return result }
public static Void main (Str[] args) { if (args.size == 1) { // process each line of given file Str filename := args[0] File(filename.toUri).eachLine |Str line| { echo (rot13(line)) } } else { echo ("Test:") Str text := "abcstuABCSTU123!+-" echo ("Text $text becomes ${rot13(text)}") } }
} </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
<lang fortran>program test_rot_13
implicit none integer, parameter :: len_max = 256 integer, parameter :: unit = 10 character (len_max) :: file character (len_max) :: fmt character (len_max) :: line integer :: arg integer :: arg_max integer :: iostat
write (fmt, '(a, i0, a)') '(a', len_max, ')' arg_max = iargc () if (arg_max > 0) then
! Encode all files listed on the command line.
do arg = 1, arg_max call getarg (arg, file) open (unit, file = file, iostat = iostat) if (iostat /= 0) cycle do read (unit, fmt = fmt, iostat = iostat) line if (iostat /= 0) exit write (*, '(a)') trim (rot_13 (line)) end do close (unit) end do else
! Encode standard input.
do read (*, fmt = fmt, iostat = iostat) line if (iostat /= 0) exit write (*, '(a)') trim (rot_13 (line)) end do end if
contains
function rot_13 (input) result (output)
implicit none character (len_max), intent (in) :: input character (len_max) :: output integer :: i
output = input do i = 1, len_trim (output) select case (output (i : i)) case ('A' : 'M', 'a' : 'm') output (i : i) = char (ichar (output (i : i)) + 13) case ('N' : 'Z', 'n' : 'z') output (i : i) = char (ichar (output (i : i)) - 13) end select end do
end function rot_13
end program test_rot_13</lang>
Note: iargc
and getarg
are common extensions that are implemented by e.g. the Intel Fortran Compiler, G95 and gfortran.
Sample usage: <lang>> cat foo.txt foo > cat bar.txt bar > ./rot_13 foo.txt bar.txt sbb one > ./rot_13 < foo.txt sbb > cat foo.txt bar.txt | ./rot_13 sbb one</lang>
GAP
<lang gap>rot13 := function(s)
local upper, lower, c, n, t; upper := "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; lower := "abcdefghijklmnopqrstuvwxyz"; t := [ ]; for c in s do n := Position(upper, c); if n <> fail then Add(t, upper[((n+12) mod 26) + 1]); else n := Position(lower, c); if n <> fail then Add(t, lower[((n+12) mod 26) + 1]); else Add(t, c); fi; fi; od; return t;
end;
a := "England expects that every man will do his duty";
- "England expects that every man will do his duty"
b := rot13(a);
- "Ratynaq rkcrpgf gung rirel zna jvyy qb uvf qhgl"
c := rot13(b);
- "England expects that every man will do his duty"</lang>
Gema
<lang gema>/[a-mA-M]/=@int-char{@add{@char-int{$1};13}} /[n-zN-Z]/=@int-char{@sub{@char-int{$1};13}}</lang>
GML
<lang GML>#define rot13 {
out = ; for (x = 1; x <= string_length(argument0); x += 1) { working = ord(string_char_at(argument0, x)); if ((working > 64) && (working < 91)) { working += 13; if (working > 90) working -= 26; } else if ((working > 96) && (working < 123)) { working += 13; if (working > 122) working -= 26; } out = out + chr(working); } return out;
}</lang>
The above code is called like this: <lang GML>show_message(rot13("My dog has fleas!"));</lang>
Output (in a message box):
Zl qbt unf syrnf!
Go
<lang go>package main
import (
"fmt" "strings"
)
func rot13char(c rune) rune {
if c >= 'a' && c <= 'm' || c >= 'A' && c <= 'M' { return c + 13 } else if c >= 'n' && c <= 'z' || c >= 'N' && c <= 'Z' { return c - 13 } return c
}
func rot13(s string) string {
return strings.Map(rot13char, s)
}
func main() {
fmt.Println(rot13("nowhere ABJURER"))
}</lang> Output:
abjurer NOWHERE
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.
GW-BASIC
<lang qbasic>10 INPUT "Enter a string: ",A$ 20 GOSUB 50 30 PRINT B$ 40 END 50 FOR I=1 TO LEN(A$) 60 N=ASC(MID$(A$,I,1)) 70 E=255 80 IF N>64 AND N<91 THEN E=90 ' uppercase 90 IF N>96 AND N<123 THEN E=122 ' lowercase 100 IF E<255 THEN N=N+13 110 IF N>E THEN N=N-26 120 B$=B$+CHR$(N) 130 NEXT 140 RETURN</lang>
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.
HicEst
<lang hicest>CHARACTER c, txt='abc? XYZ!', cod*100
DO i = 1, LEN_TRIM(txt) c = txt(i) n = ICHAR(txt(i)) IF( (c >= 'a') * (c <= 'm') + (c >= 'A') * (c <= 'M') ) THEN c = CHAR( ICHAR(c) + 13 ) ELSEIF( (c >= 'n') * (c <= 'z') + (c >= 'N') * (c <= 'Z') ) THEN c = CHAR( ICHAR(c) - 13 ) ENDIF
cod(i) = c ENDDO
WRITE(ClipBoard, Name) txt, cod ! txt=abc? XYZ!; cod=nop? KLM!;
END</lang>
Icon and Unicon
<lang Icon>procedure main(arglist)
file := open(arglist[1],"r") | &input every write(rot13(|read(file)))
end
procedure rot13(s) #: returns rot13(string) static a,n initial {
a := &lcase || &ucase (&lcase || &lcase) ? n := ( move(13), move(*&lcase) ) (&ucase || &ucase) ? n ||:= ( move(13), move(*&ucase) ) }
return map(s,a,n) end</lang> This example uses a number of Icon features.
- alternation ( x | y ) selects and opens a file if supplied or fall back to standard output
- repeated alternation ( |x ) is used to generate the contents of the input file
- the rot13 procedure does a one time setup (initially) of persistent (static) mapping strings so the procedure can return the rot13 mapping
- the setup exploits the ordered cset variables &lcase and &ucase coercing them into strings
- the rot13 mapping string is then aggregated with strings taken by offsetting into double length values to avoid unnecessary and messy rotation
J
<lang j>rot13=: {&((65 97+/~i.2 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.*;
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 (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) { StringBuilder retVal = new StringBuilder(); 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.append(a); } return retVal.toString(); }
}</lang>
JavaScript
<lang javascript>function rot13(c) {
return c.replace(/([a-m])|([n-z])/ig, function($0,$1,$2) { return String.fromCharCode($1 ? $1.charCodeAt(0) + 13 : $2 ? $2.charCodeAt(0) - 13 : 0) || $0; });
} rot13("ABJURER nowhere") // NOWHERE abjurer </lang>
K
<lang k> rot13: {a:+65 97+\:2 13#!26;_ci@[!256;a;:;|a]_ic x}
rot13 "Testing! 1 2 3"
"Grfgvat! 1 2 3"</lang>
LabVIEW
This image is a VI Snippet, an executable image of LabVIEW code. The LabVIEW version is shown on the top-right hand corner. You can download it, then drag-and-drop it onto the LabVIEW block diagram from a file browser, and it will appear as runnable, editable code.
Liberty BASIC
Liberty BASIC string comparisons are not ascii-based. Verbose version: <lang lb>input "Type some text to be encoded, then ENTER. ";tx$
tex$ = Rot13$(tx$) print tex$ 'check print Rot13$(tex$)
wait
Function Rot13$(t$)
if t$="" then Rot13$="" exit function end if for i = 1 to len(t$) c$=mid$(t$,i,1) ch$=c$ if (asc(c$)>=asc("A")) and (asc(c$)<=asc("Z")) then ch$=chr$(asc(c$)+13) if (asc(ch$)>asc("Z")) then ch$=chr$(asc(ch$)-26) end if if (asc(c$)>=asc("a")) and (asc(c$)<=asc("z")) then ch$=chr$(asc(c$)+13) if (asc(ch$)>asc("z")) then ch$=chr$(asc(ch$)-26) end if rot$=rot$+ch$ next Rot13$=rot$ end function </lang>
Concise: <lang lb>Function Rot13$(t$)
for i = 1 to len(t$) ch$=mid$(t$,i,1) if (asc(ch$)>=asc("A")) and (asc(ch$)<=asc("Z")) then ch$=chr$(asc("A")+ (asc(ch$)-asc("A")+13) mod 26) end if if (asc(ch$)>=asc("a")) and (asc(ch$)<=asc("z")) then ch$=chr$(asc("a")+ (asc(ch$)-asc("a")+13) mod 26) end if Rot13$=Rot13$+ch$ next end function
</lang>
Locomotive Basic
<lang locobasic>10 INPUT "Enter a string: ",a$ 20 GOSUB 50 30 PRINT b$ 40 END 50 FOR i=1 TO LEN(a$) 60 n=ASC(MID$(a$,i,1)) 70 e=255 80 IF n>64 AND n<91 THEN e=90 ' uppercase 90 IF n>96 AND n<123 THEN e=122 ' lowercase 100 IF e<255 THEN n=n+13 110 IF n>e THEN n=n-26 120 b$=b$+CHR$(n) 130 NEXT 140 RETURN</lang>
Logo
<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>ruleslower=Thread[#-> RotateLeft[#, 13]]&[CharacterRange["a", "z"]]; rulesupper=Thread[#-> RotateLeft[#, 13]]&[CharacterRange["A", "Z"]]; rules=Join[ruleslower,rulesupper]; text="Hello World! Are you there!?" text=StringReplace[text,rules] text=StringReplace[text,rules]</lang> gives back:
Hello World! Are you there!? Uryyb Jbeyq! Ner lbh gurer!? Hello World! Are you there!?
MATLAB
<lang matlab>function r=rot13(s)
if ischar(s) r=s; % preallocation and copy of non-letters for i=1:size(s,1) for j=1:size(s,2) if isletter(s(i,j)) if s(i,j)>=97 % lower case base = 97; else % upper case base = 65; end r(i,j)=char(mod(s(i,j)-base+13,26)+base); end end end else error('Argument must be a CHAR') end
end</lang> Call it like this: <lang matlab>>> rot13('Hello World!')
ans =
Uryyb Jbeyq!</lang>
It is possible to vectorize this code, the example below is not fully vectorized in order to make the order of operations clear. It is possible to reduce this solution to two lines by integrating the "selectedLetters" calculations directly into the line following them.
<lang MATLAB>function text = rot13(text)
if ischar(text) selectedLetters = ( (text >= 'A') & (text <= 'Z') ); %Select upper case letters text(selectedLetters) = char( mod( text(selectedLetters)-'A'+13,26 )+'A' ); selectedLetters = ( (text >= 'a') & (text <= 'z') ); %Select lower case letters text(selectedLetters) = char( mod( text(selectedLetters)-'a'+13,26 )+'a' );
else error('Argument must be a string.') end
end</lang>
Sample Output: <lang MATLAB>>> plainText = char((64:123))
plainText =
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{
>> rot13(plainText)
ans =
@NOPQRSTUVWXYZABCDEFGHIJKLM[\]^_`nopqrstuvwxyzabcdefghijklm{</lang>
Mirah
<lang mirah>def rot13 (value:string)
result = "" d = ' '.toCharArray[0] value.toCharArray.each do |c| testChar = Character.toLowerCase(c) if testChar <= 'm'.toCharArray[0] && testChar >= 'a'.toCharArray[0] then d = char(c + 13) end if testChar <= 'z'.toCharArray[0] && testChar >= 'n'.toCharArray[0] then d = char(c - 13) end result += d end result
end
puts rot13("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")</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
MUMPS
<lang MUMPS>Rot13(in) New low,rot,up Set up="ABCDEFGHIJKLMNOPQRSTUVWXYZ" Set low="abcdefghijklmnopqrstuvwxyz" Set rot=$Extract(up,14,26)_$Extract(up,1,13) Set rot=rot_$Extract(low,14,26)_$Extract(low,1,13) Quit $Translate(in,up_low,rot)
Write $$Rot13("Hello World!") ; Uryyb Jbeyq! Write $$Rot13("ABCDEFGHIJKLMNOPQRSTUVWXYZ") ; NOPQRSTUVWXYZABCDEFGHIJKLM</lang>
NetRexx
This sample leverages the code demonstrated in the Caesar cipher – NetRexx task. <lang NetRexx>/* NetRexx */ options replace format comments java crossref savelog symbols nobinary
parse arg fileNames
rdr = BufferedReader
do
if fileNames.length > 0 then do loop n_ = 1 for fileNames.words fileName = fileNames.word(n_) rdr = BufferedReader(FileReader(File(fileName))) encipher(rdr) end n_ end else do rdr = BufferedReader(InputStreamReader(System.in)) encipher(rdr) end
catch ex = IOException
ex.printStackTrace
end
return
method encipher(rdr = BufferedReader) public static signals IOException
loop label l_ forever line = rdr.readLine if line = null then leave l_ say rot13(line) end l_ return
method rot13(input) public static signals IllegalArgumentException
return caesar(input, 13, isFalse)
method caesar(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException
if idx < 1 | idx > 25 then signal IllegalArgumentException()
-- 12345678901234567890123456 itab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' shift = itab.length - idx parse itab tl +(shift) tr otab = tr || tl
if caps then input = input.upper
cipher = input.translate(itab || itab.lower, otab || otab.lower)
return cipher
method caesar_encipher(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException
return caesar(input, idx, caps)
method caesar_decipher(input = Rexx, idx = int, caps = boolean) public static signals IllegalArgumentException
return caesar(input, int(26) - idx, isFalse)
method caesar_encipher(input = Rexx, idx = int) public static signals IllegalArgumentException
return caesar(input, idx, isFalse)
method caesar_decipher(input = Rexx, idx = int) public static signals IllegalArgumentException
return caesar(input, int(26) - idx, isFalse)
method caesar_encipher(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException
return caesar(input, idx, opt)
method caesar_decipher(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException
return caesar(input, int(26) - idx, opt)
method caesar(input = Rexx, idx = int, opt = Rexx) public static signals IllegalArgumentException
if opt.upper.abbrev('U') >= 1 then caps = isTrue else caps = isFalse
return caesar(input, idx, caps)
method caesar(input = Rexx, idx = int) public static signals IllegalArgumentException
return caesar(input, idx, isFalse)
method isTrue public static returns boolean
return (1 == 1)
method isFalse public static returns boolean
return \isTrue
</lang>
Output (using the source file as input):
/* ArgErkk */ bcgvbaf ercynpr sbezng pbzzragf wnin pebffers fnirybt flzobyf abovanel cnefr net svyrAnzrf eqe = OhssrerqErnqre qb vs svyrAnzrf.yratgu > 0 gura qb ybbc a_ = 1 sbe svyrAnzrf.jbeqf svyrAnzr = svyrAnzrf.jbeq(a_) eqe = OhssrerqErnqre(SvyrErnqre(Svyr(svyrAnzr))) rapvcure(eqe) raq a_ raq ryfr qb eqe = OhssrerqErnqre(VachgFgernzErnqre(Flfgrz.va)) rapvcure(eqe) raq pngpu rk = VBRkprcgvba rk.cevagFgnpxGenpr raq erghea zrgubq rapvcure(eqe = OhssrerqErnqre) choyvp fgngvp fvtanyf VBRkprcgvba ybbc ynory y_ sberire yvar = eqe.ernqYvar vs yvar = ahyy gura yrnir y_ fnl ebg13(yvar) raq y_ erghea zrgubq ebg13(vachg) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, 13, vfSnyfr) zrgubq pnrfne(vachg = Erkk, vqk = vag, pncf = obbyrna) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba vs vqk < 1 | vqk > 25 gura fvtany VyyrtnyNethzragRkprcgvba() -- 12345678901234567890123456 vgno = 'NOPQRSTUVWXYZABCDEFGHIJKLM' fuvsg = vgno.yratgu - vqk cnefr vgno gy +(fuvsg) ge bgno = ge || gy vs pncf gura vachg = vachg.hccre pvcure = vachg.genafyngr(vgno || vgno.ybjre, bgno || bgno.ybjre) erghea pvcure zrgubq pnrfne_rapvcure(vachg = Erkk, vqk = vag, pncf = obbyrna) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vqk, pncf) zrgubq pnrfne_qrpvcure(vachg = Erkk, vqk = vag, pncf = obbyrna) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vag(26) - vqk, vfSnyfr) zrgubq pnrfne_rapvcure(vachg = Erkk, vqk = vag) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vqk, vfSnyfr) zrgubq pnrfne_qrpvcure(vachg = Erkk, vqk = vag) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vag(26) - vqk, vfSnyfr) zrgubq pnrfne_rapvcure(vachg = Erkk, vqk = vag, bcg = Erkk) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vqk, bcg) zrgubq pnrfne_qrpvcure(vachg = Erkk, vqk = vag, bcg = Erkk) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vag(26) - vqk, bcg) zrgubq pnrfne(vachg = Erkk, vqk = vag, bcg = Erkk) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba vs bcg.hccre.nooeri('H') >= 1 gura pncf = vfGehr ryfr pncf = vfSnyfr erghea pnrfne(vachg, vqk, pncf) zrgubq pnrfne(vachg = Erkk, vqk = vag) choyvp fgngvp fvtanyf VyyrtnyNethzragRkprcgvba erghea pnrfne(vachg, vqk, vfSnyfr) zrgubq vfGehr choyvp fgngvp ergheaf obbyrna erghea (1 == 1) zrgubq vfSnyfr choyvp fgngvp ergheaf obbyrna erghea \vfGehr
Objeck
<lang objeck> bundle Default {
class Rot13 { function : Main(args : String[]) ~ Nil { Rot13("nowhere ABJURER")->PrintLine(); }
function : native : Rot13(text : String) ~ String { rot := ""; each(i : text) { c := text->Get(i); if(c >= 'a' & c <= 'm' | c >= 'A' & c <= 'M') { rot->Append(c + 13); } else if(c >= 'n' & c <= 'z' | c >= 'N' & c <= 'Z') { rot->Append(c - 13); } else { rot->Append(c); }; };
return rot; } }
} </lang>
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>
And here is a utility program that converts the content read on sdtin
and write it to stdout
:
<lang ocaml>let () =
try while true do String.iter (fun c -> print_char (rot13 c)) (read_line()); print_newline() done with End_of_file -> ()</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>
PARI/GP
<lang parigp>rot13(s)={
s=Vecsmall(s); for(i=1,#s, if(s[i]>109&s[i]<123,s[i]-=13,if(s[i]<110&s[i]>96,s[i]+=13,if(s[i]>77&s[i]<91,s[i]-=13,if(s[i]<78&s[i]>64,s[i]+=13)))) ); Strchr(s)
};</lang>
Pascal
<lang Pascal>program rot13(input, output);
function rot13(someText: string): string; var
i: integer; ch: char; resultText: string = ;
begin
for i := 1 to Length(someText) do begin ch := someText[i]; case ch of 'A' .. 'M', 'a' .. 'm': ch := chr(ord(ch)+13); 'N' .. 'Z', 'n' .. 'z': ch := chr(ord(ch)-13) end; resultText := resultText + ch end; rot13 := resultText
end;
var
line: string;
begin
while not eof(input) do begin readln(line); writeln(rot13(line)) end
end.</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
<lang perl6>sub rot13 ($s) { $s.trans('A..Za..z' => 'N..ZA..Mn..za..m') }
multi MAIN () {
print rot13 ~$*IN.slurp;
}
multi MAIN (*@files) {
print rot13 [~] map &slurp, @files;
}</lang>
This illustrates use of multi-dispatch to MAIN based on number of arguments.
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
PicoLisp
<lang PicoLisp>(de rot13-Ch (C)
(if (or (member C '`(apply circ (chop "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))) (member C '`(apply circ (chop "abcdefghijklmnopqrstuvwxyz"))) ) (get @ 14) C ) )</lang>
or: <lang PicoLisp>(de rot13-Ch (C)
(cond ((>= "M" (uppc C) "A") (char (+ (char C) 13)) ) ((>= "Z" (uppc C) "N") (char (- (char C) 13)) ) (T C) ) )</lang>
Then call it as: <lang PicoLisp>(de rot13-stdIn ()
(while (line) (prinl (mapcar rot13-Ch @)) ) )</lang>
Pike
<lang pike> import Crypto;
int main(){
string r = rot13("Hello, World"); write(r + "\n");
} </lang>
PL/I
<lang PL/I> rotate: procedure (in) options (main); /* 2 March 2011 */
declare in character (100) varying; declare line character (500) varying; declare input file;
open file (input) title ('/' || in || ',type(text),recsize(500)' );
on endfile (input) stop;
do forever; get file (input) edit (line) (L); line = translate ( line, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm'); put edit (line) (a); put skip; end;
end; </lang> Data file:
"The time has come," the walrus said, "to speak of many things; of ships and shoes and sealing wax; of cabbages and kings."
Output:
"Gur gvzr unf pbzr," gur jnyehf fnvq, "gb fcrnx bs znal guvatf; bs fuvcf naq fubrf naq frnyvat jnk; bs pnoontrf naq xvatf."
PostScript
<lang postscript> /r13 { 4 dict begin
/rotc { { {{{64 gt} {91 lt}} all?} {65 - 13 + 26 mod 65 +} is? {{{95 gt} {123 lt}} all?} {97 - 13 + 26 mod 97 +} is? } cond }. {rotc} map cvstr
end}. </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>
PowerShell
<lang powershell> Function ROT13($String) { $Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " $Cipher = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm " Foreach($Char in $String.ToCharArray()) { $NewString += $Cipher.Chars($Alphabet.IndexOf($Char)) } Return $NewString } </lang>
Prolog
Works with SWI-Prolog. <lang Prolog>rot13(Str, SR) :- maplist(rot, Str, Str1), string_to_list(SR, Str1).
rot(C, C1) :- ( member(C, "abcdefghijklmABCDEFGHIJKLM") -> C1 is C+13; ( member(C, "nopqrstuvwxyzNOPQRSTUVWXYZ") -> C1 is C-13; C1 = C)). </lang> Output : <lang Prolog> ?- rot13("The Quick Brown Fox Jumped Over The Lazy Dog!", SR). SR = "Gur Dhvpx Oebja Sbk Whzcrq Bire Gur Ynml Qbt!".</lang>
PureBasic
<lang PureBasic>Declare.s Rot13(text_to_code.s)
If OpenConsole()
Define txt$ Print("Enter a string to encode: "): txt$=Input() PrintN("Coded : "+Rot13(txt$)) PrintN("Decoded: "+Rot13(Rot13(txt$))) Print("Press ENTER to quit."): Input() CloseConsole()
EndIf
Procedure.s Rot13(s.s)
Protected.i i Protected.s t, u For i=1 To Len(s) t=Mid(s,i,1) Select Asc(t) Case Asc("a") To Asc("m"), Asc("A") To Asc("M") t=chr(Asc(t)+13) Case Asc("n") To Asc("z"), Asc("N") To Asc("Z") t=chr(Asc(t)-13) EndSelect u+t Next ProcedureReturn u
EndProcedure</lang>
Python
Python 2.x (but not 3.x) has built-in rot13 encoding and decoding:
>>> u'foo'.encode('rot13') 'sbb' >>> 'sbb'.decode('rot13') u'foo'
Here is an implementation:
<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).
In Python 3.x, the string.maketrans() function actually only works for the bytes type, and has been deprecated since 3.1. If you want to work on strings (str type), you need to use str.maketrans(): <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!
Retro
<lang retro>{{
: rotate ( cb-c ) tuck - 13 + 26 mod + ; : rotate? ( c-c ) dup 'a 'z within [ 'a rotate ] ifTrue dup 'A 'Z within [ 'A rotate ] ifTrue ;
---reveal---
: rot13 ( s-s ) dup [ [ @ rotate? ] sip ! ] ^types'STRING each@ ;
}}
"abcdef123GHIJKL" rot13 dup puts cr rot13 puts "abjurer NOWHERE" rot13 puts</lang>
REXX
<lang rexx> aa='foo' say 'simple text='aa say ' rot13 text='rot13(aa) say
bb='bar' say 'simple text='bb say ' rot13 text='rot13(bb) say
cc="Noyr jnf V, 'rer V fnj Ryon." say 'simple text='cc say ' rot13 text='rot13(cc) say
dd='abc? ABC!' say 'simple text='dd say ' rot13 text='rot13(dd) say
ee='abjurer NOWHERE' say 'simple text='ee say ' rot13 text='rot13(ee) say
exit
/*----------------------ROT13 subroutine----------------*/ rot13: return translate(arg(1),,
'abcdefghijklmABCDEFGHIJKLMnopqrstuvwxyzNOPQRSTUVWXYZ',, 'nopqrstuvwxyzNOPQRSTUVWXYZabcdefghijklmABCDEFGHIJKLM')
</lang> Output:
simple text=foo rot13 text=sbb simple text=bar rot13 text=one simple text=Noyr jnf V, 'rer V fnj Ryon. rot13 text=Able was I, 'ere I saw Elba. simple text=abc? ABC! rot13 text=nop? NOP! simple text=abjurer NOWHERE rot13 text=nowhere ABJURER
Ruby
<lang ruby># Returns a copy of _s_ with rot13 encoding. def rot13(s)
s.tr('A-Za-z', 'N-ZA-Mn-za-m')
end
- Perform rot13 on files from command line, or standard input.
while line = ARGF.gets
print rot13(line)
end</lang>
One can run ruby rot13.rb file1 file2
to rot13 those files, or run ruby rot13.rb
to rot13 the standard input.
Input:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
Output:
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
Run BASIC
<lang runbasic>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) else if 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>Output:
Enter a string: ?abc nop Enter a string: ?ABC NOP
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
<lang scheme>(define (rot13 str)
(define (rot13-char c) (integer->char (+ (char->integer c) (cond ((and (char>=? c #\a) (char<? c #\n)) 13) ((and (char>=? c #\A) (char<? c #\N)) 13) ((and (char>=? c #\n) (char<=? c #\z)) -13) ((and (char>=? c #\N) (char<=? c #\Z)) -13) (else 0))))) (list->string (map rot13-char (string->list str))))
</lang>
sed
The two translations (upper and lower case) are separate only for documentation and ease of understanding; they could be combined into one command. <lang sed>y/abcdefghijklmnopqrstuvwxyz/nopqrstuvwxyzabcdefghijklm/ y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/NOPQRSTUVWXYZABCDEFGHIJKLM/</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 ::= ch isUppercase. value := ch toLowercase as: Integer. (value >= 97) /\ [value < 110] ifTrue: [value += 13] ifFalse: [(value > 109) /\ [value <= 122] ifTrue: [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 ::= ch isUppercase. value := ch toLowercase as: Integer. (value >= 97) /\ [value < 110] ifTrue: [value += 13] ifFalse: [(value > 109) /\ [value <= 122] ifTrue: [value -= 13]]. upper ifTrue: [(value as: String Character) toUppercase] ifFalse: [value as: String Character]
].
s@(String traits) rot13 [
result ::= s newSameSize. s doWithIndex: [| :each :index | result at: index put: each rot13]. result
].
slate[37]> 'abc123' rot13. 'nop123'</lang>
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>
SNOBOL4
<lang SNOBOL4>* # Function using replace( )
define('rot13(s)u1,u2,l1,l2') :(rot13_end)
rot13 &ucase len(13) . u1 rem . u2
&lcase len(13) . l1 rem . l2 rot13 = replace(s,&ucase &lcase,u2 u1 l2 l1) :(return)
rot13_end
- # Function using pattern
define('rot13s(s)c') alfa = &ucase &ucase &lcase &lcase :(rot13s_end)
rot13s s len(1) . c = :f(return)
alfa break(c) len(13) len(1) . c rot13s = rot13s c :(rot13s)
rot13s_end
- # Test and display both
str = rot13("I abjure the $19.99 trinket!") output = str; output = rot13(str) str = rot13s("He's a real Nowhere Man.") output = str; output = rot13s(str)
end</lang>
Output:
V nowher gur $19.99 gevaxrg! I abjure the $19.99 trinket! Ur'f n erny Abjurer Zna. He's a real Nowhere Man.
Standard ML
<lang sml>fun rot13char c =
if c >= #"a" andalso c <= #"m" orelse c >= #"A" andalso c <= #"M" then chr (ord c + 13) else if c >= #"n" andalso c <= #"z" orelse c >= #"N" andalso c <= #"Z" then chr (ord c - 13) else c
val rot13 = String.map rot13char</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
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>
TXR
Via definition and subsequent use of a named filter.
<lang txr>@(deffilter rot13
("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"))
@(collect :vars ()) @line @ (output :filter rot13) @line @ (end) @(end)</lang>
The :vars ()
argument to collect
means that it still iterates, but doesn't actually collect anything (empty list of variables). This is important, so that there isn't a growing data structure being accumulated as the input is processed.
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]' }
cat ${1+"$@"} | rot13</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. A simple tr a-zA-Z n-za-mN-ZA-M
would work with modern systems that follow POSIX. Our tr '[a-m][n-z][A-M][N-Z]' '[n-z][a-m][N-Z][A-M]'
also works with those older System V systems. For newer systems, it translates '[' and ']' to themselves. (Refer to OpenBSD tr(1) manual page, section STANDARDS.)
This example shows proper quoting around "$@" (magical argument list) such that this script work properly even if some of the files named on the command line contain embedded spaces or other such characters. (The ${1+"$@"} check, unnecessary in modern systems, allows the script to work even on older systems where a bare "$@" expanded to a single empty string when no arguments were supplied).
Unlambda
<lang Unlambda>``ci`d``@i`c``s`d```?aic.n``s`d```?bic.o``s`d```?cic.p``s`d```?dic.q``s`d```?eic .r``s`d```?fic.s``s`d```?gic.t``s`d```?hic.u``s`d```?iic.v``s`d```?jic.w``s`d``` ?kic.x``s`d```?lic.y``s`d```?mic.z``s`d```?nic.a``s`d```?oic.b``s`d```?pic.c``s` d```?qic.d``s`d```?ric.e``s`d```?sic.f``s`d```?tic.g``s`d```?uic.h``s`d```?vic.i ``s`d```?wic.j``s`d```?xic.k``s`d```?yic.l``s`d```?zic.m``s`d```?Nic.A``s`d```?O ic.B``s`d```?Pic.C``s`d```?Qic.D``s`d```?Ric.E``s`d```?Sic.F``s`d```?Tic.G``s`d` ``?Uic.H``s`d```?Vic.I``s`d```?Wic.J``s`d```?Xic.K``s`d```?Yic.L``s`d```?Zic.M`` s`d```?Aic.N``s`d```?Bic.O``s`d```?Cic.P``s`d```?Dic.Q``s`d```?Eic.R``s`d```?Fic .S``s`d```?Gic.T``s`d```?Hic.U``s`d```?Iic.V``s`d```?Jic.W``s`d```?Kic.X``s`d``` ?Lic.Y``s`d```?Mic.Z`d`|c</lang>
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
- 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
<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.
X86 Assembly
Using Linux/FASM. <lang asm>format ELF executable 3 entry start
segment readable writeable buf rb 1
segment readable executable start: mov eax, 3 ; syscall "read" mov ebx, 0 ; stdin mov ecx, buf ; buffer for read byte mov edx, 1 ; len (read one byte) int 80h
cmp eax, 0 ; EOF? jz exit
xor eax, eax ; load read char to eax mov al, [buf] cmp eax, "A" ; see if it is in ascii a-z or A-Z jl print cmp eax, "z" jg print cmp eax, "Z" jle rotup cmp eax, "a" jge rotlow jmp print
rotup: sub eax, "A"-13 ; do rot 13 for A-Z cdq mov ebx, 26 div ebx add edx, "A" jmp rotend
rotlow: sub eax, "a"-13 ; do rot 13 for a-z cdq mov ebx, 26 div ebx add edx, "a"
rotend: mov [buf], dl
print: mov eax, 4 ; syscall write mov ebx, 1 ; stdout mov ecx, buf ; *char mov edx, 1 ; string length int 80h
jmp start
exit: mov eax,1 ; syscall exit xor ebx,ebx ; exit code int 80h</lang>
XPL0
Usage: rot13 <infile.txt >outfile.txt <lang XPL0>code ChIn=7, ChOut=8; int C, CC; repeat C:= ChIn(1); CC:= C&~$20; \CC handles lowercase too
ChOut(0, C + (if CC>=^A & CC<=^M then +13 else if CC>=^N & CC<=^Z then -13 else 0));
until C = $1A; \EOF</lang>
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.
ZX Spectrum Basic
<lang zxbasic>5 REM Translation of the QBasic provided solution 10 CLS 20 INPUT "Enter a string: ", s$ 30 LET a$ = "": REM a$ is the encoded string 40 FOR l = 1 TO LEN(s$) 50 LET i$ = s$(l): REM i$ is the letter being worked on 60 IF i$ < "A" OR i$ > "Z" THEN GO TO 100 70 LET c$ = CHR$(CODE(i$) + 13): REM c$ is the encoded letter 80 IF c$ > "Z" THEN LET c$ = CHR$(CODE(c$) - 26) 90 GO TO 300 100 IF i$ < "a" OR i$ > "z" THEN GO TO 200 110 LET c$ = CHR$(CODE(i$) + 13) 120 IF c$ > "z" THEN LET c$ = CHR$(CODE(c$) - 26) 130 GO TO 300 200 LET c$ = i$ 300 LET a$ = a$ + c$ 310 NEXT l 320 PRINT a$</lang>