ROT13
February 20, 2009
This code is available at http://programmingpraxis.codepad.org/xSLxDTmO:
(define (rot13 s)
(define (char-plus c n)
(integer->char (+ n (char->integer c))))
(define (rot c)
(cond ((char<=? #\a c #\m) (char-plus c 13))
((char<=? #\n c #\z) (char-plus c -13))
((char<=? #\A c #\M) (char-plus c 13))
((char<=? #\N c #\Z) (char-plus c -13))
(else c)))
(list->string (map rot (string->list s))))
> (rot13 "Cebtenzzvat Cenkvf vf sha!")
"Programming Praxis is fun!"
This is a rather trivial exercise for Oracle’s PL/SQL since it has a TRANSLATE function. This function translates each character in a given string using “from” and “to” positional strings, passed as parameters (along with the target string, of course). Each character in the target string found in the “from” string is replaced by the corresponding character in the “to” string. Quite handy, especially for doing ROT13. But as you can see, I only included a couple of special characters in the translation strings, so my first implementation was rather limited:
function rot13(parm_str in varchar2) return varchar2 is begin return translate(parm_str, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz.,!?', 'NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm.,!?') ; end rot13 ;Rather than adding all the non-alphabetics I could type, I decided to write my own simple translation logic to handle any ASCII character:
function rot13(parm_str in varchar2) return varchar2 is
j pls_integer ;
parm_ret varchar2(1000) := null ;
begin
for i in 1..length(parm_str)
loop
j := ascii(substr(parm_str,i,1)) ;
case
when j>=65 and j<=90 /* A-Z */ then j:=j-13 ; if j<65 then j:=j+26; end if ; when j>=97 and j<=122 /* a-z */ then j:=j-13; if j<97 then j:=j+26; end if ; else null ; end case ; parm_ret := parm_ret||chr(j); end loop ; return parm_ret ; end rot13 ; [/sourcecode] Simple, but it works.
Not too hard in perl:
y/A-Za-z/N-ZA-Mn-za-m/;
import Maybe (fromMaybe)
import Data.List (find)
genTab :: Int -> [(Char, Char)]
genTab rot = zip (['a'..'z'] ++ ['A'..'Z']) (take 26 (drop rot (cycle ['a'..'z'])) ++
take 26 (drop rot (cycle ['A'..'Z'])))
{- apply the cipher function to the string. It substitutes values obtained from the
lookup table, generated by the function genTab -}
rotFunc :: Int -> String -> String
rotFunc rot str = map cipher str
where cipher c = (snd (fromMaybe (c,c) (find (\ x -> (fst x) == c) (genTab rot))))
rot13 :: String -> String
rot13 = rotFunc 13
Alternative Haskell approach:
My OCaml version.
let rot13 s =
let rotate c =
let aux i = char_of_int ( i + (int_of_char c – i + 13) mod 26) in
match c with
| ‘A’..’Z’ -> aux 65
| ‘a’..’z’ -> aux 97
| _ -> c
in
for i = 0 to String.length s – 1 do s.[i] <- rotate s.[i] done let _ = let s = "Cebtenzzvat Cenkvf vf sha!" in rot13 s; print_endline s [/sourcecode]
Very simple python solution, but makes everything lowercase
from string import ascii_lowercase, maketrans, translate def rot13(s): return translate(s.lower(), maketrans(ascii_lowercase, ascii_lowercase[13:] + ascii_lowercase[:13]))def rotate(ox, base):
return chr(base + ((ox – base) + 13) % 26)
def handle(x):
ox = ord(x)
if ord(“a”) <= ox and ox <= ord("z"): return rotate(ox, ord("a")) elif ord("A") <= ox and ox <= ord("Z"): return rotate(ox, ord("A")) else: return x def rot13(input): return "".join(map(handle, input)) [/sourcecode] >>> rot13("Cebtenzzvat Cenkvf vf sha!") 'Programming Praxis is fun!'
A solution in SML.
(* ROT13 cipher *)
(* see: http://programmingpraxis.com/2009/02/20/rot13/ *)
fun rot13 (str : string) : string =
let
fun wrapTo (ch : char, top : char) : char =
let
val next = Char.ord ch + 13
in
if next > Char.ord top then
Char.chr (next – 26)
else
Char.chr (next)
end
fun rotChar (ch : char) : char =
if ch >= #”a” andalso ch <= #”z” then
wrapTo (ch, #”z”)
else if ch >= #”A” andalso ch <= #”z” then
wrapTo (ch, #”Z”)
else
ch
in
String.map rotChar str
end
Thought this would be nice in ruby …
class String def rot13 self.tr('A-Za-z.!(),', 'N-ZA-Mn-za-m.!(),') end end # Should print Programming Praxis is fun! puts "Cebtenzzvat Cenkvf vf sha!".rot13Adding rot13 to the String class makes it available for all Strings. Kind of a nice feature.
Python – a more functional & less readable approach:
from string import letters from string import lowercase from string import uppercase def get_shifted(text, numlet=26, num=13): shift = lambda x: (x + num) % numlet llist = lambda let : [[let[x], let[shift(x)]] for x in range(numlet)] shifted = dict(llist(uppercase) + llist(lowercase)) return "".join([shifted[s] if s in letters else s for s in text]) if __name__ == '__main__': print get_shifted("Cebtenzzvat Cenkvf vf sha!")[…] this ProgrammingPraxis challenge we have to build a simple Caesar Cipher variant called rot13 […]
This is probably much longer than it has to be, but here is my solution in python:
alpha = {
‘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’}
txt = input(‘Text to cypher with rot13: ‘)
txtlst = list(txt)
count = 0
while count < len(txtlst):
let = txtlst[count]
txtlst[count] = alpha[let]
count+=1
rotd = "".join(txtlst)
print(txt+" becomes "+rotd)
Tcl
#
# Gives a version that doesn’t require any additional procedures, and rotates by any amount (specified by an optional second argument,
# defaults to 13 of course) — And supports negative rotation amounts
#
proc rot {text {amount 13}} {
if {abs($amount) > 25} {
set amount [expr {$amount % 26}]
}
set alphabet “ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz”
set res “”
set length [string length $text]
set find_command [expr {$amount > 0 ? “first” : “last”}]
for {set index 0} {$index < $length} {incr index} {
set char [string index $text $index]
set pos [string $find_command $char $alphabet]
append res [expr {$pos == -1 ? $char : [string index $alphabet [expr {$pos + $amount}]]}]
}
return $res
}
#!/usr/bin/env python
def ROT13(plain):
cypher = ”
for char in plain:
if char.isalpha():
raw = ord(char)
if raw in range(97,110) or raw in range(65,78):
char = chr(raw+13)
else:
char = chr(raw-13)
cypher = cypher + char
return cypher
if __name__ == ‘__main__’:
print ROT13(‘Cebtenzzvat Cenkvf vf sha!’)
And here is my example in Python:
shift = 13 def rot13(mystr): smallZ = ord('z') bigZ = ord('Z') strOrdLst = map(ord, mystr) strDict = zip(mystr, strOrdLst) res = '' for key, value in strDict: if key.isupper(): if value + shift > bigZ: res += chr(value - shift) else: res += chr(value + shift) elif key.islower(): if value + shift > smallZ: res += chr(value - shift) else: res += chr(value + shift) else: res += key return res print(rot13('Cebtenzzvat Cenkvf vf sha!'))My version in Haskell:
import Data.Char rot13 :: String -> [Int] rot13 [x] = if (ord x) < 110 then (map (\x -> (x + 13)) [ord x]) else (map (\x -> (x - 13)) [ord x]) rot13 (x:xs) = rot13 [x] ++ rot13 xs solution :: String -> String solution [x] = map (\x -> chr x) (rot13 [x]) solution (x:xs) = solution [x] ++ solution xsGoLang
func rot13(s string) string { return strings.Map(func(c rune) rune { switch { case unicode.IsLetter(c + ROT): return c + ROT case unicode.IsLetter(c - ROT): return c - ROT } return c }, s) }golang
package main import ( "fmt" "strings" ) func rot13r(r rune) rune { if x := strings.IndexRune("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", r); x >= 0 { return rune("NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"[x]); } return r } func rot13(s string) string { return strings.Map(rot13r, s) } func main() { fmt.Printf("%s\n", rot13("Cebtenzzvat Cenkvf vf sha!")) }https://github.com/ftt/programming-praxis/blob/master/20090220-rot13/rot13.py
ugly ruby code (http://codepad.org/zldHFsDm)
Java solution:
//ROT 13 function String input = "Cebtenzzvat Cenkvf vf sha!"; String output = new String(); for(int i = 0; i < input.length(); i++){ char ch = input.charAt(i); if(Character.isLetter(ch)){ if(Character.toLowerCase(ch) > 'm'){ ch -= 13; }else ch += 13; } output = output.concat(String.valueOf(ch)); } System.out.println("In: " + input); System.out.println("Out: " + output);Python. Not sure about efficiency, but I got to play with strings.
import string
def rot13(input):
shift = 13
lst = list(input)
c = 0
while c = 97 and i = 65 and i <= 90 : # [A-Z]
lst[c] = (chr(( i-65-shift)%26 + 65))
c += 1
return ''.join(map(''.join,lst))
print(rot13('The butler did it!')) # Gur ohgyre qvq vg!
Python, also attempting to format correctly… sorry for double post.
import string def rot13(input): shift = 13 lst = list(input) c = 0 while c < len(lst): i = ord(lst[c]) if i >= 97 and i <= 122: # [a-z] lst[c] = (chr( (i-97-shift)%26 + 97)) if i >= 65 and i <= 90 : # [A-Z] lst[c] = (chr(( i-65-shift)%26 + 65)) c += 1 return ''.join(map(''.join,lst)) print(rot13('The butler did it!')) # Gur ohgyre qvq vg!in coffeescript:
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
gistfile1.txt
hosted with ❤ by GitHub
Reblogged this on graveborn and commented:
The following is the source code to my solution to the 6th problem – “ROT13: A simple Caesar-shift cipher” – of Programming Praxis, and my first program for the Amstrad Plus.
I don’t know if the additional features of the Amstrad Plus are accessible through CP/M and Pascal, but my goal when programming the following solution was merely to gain a little familiarity with using the Amstrad Plus, eg. a familiarity with editing, saving, and loading text files, and erasing files.
PROGRAM ROT13; CONST kMaxStringLength = 80; TYPE String = RECORD l : 0..kMaxStringLength; s : ARRAY [ 1..kMaxStringLength ] OF CHAR END; VAR gS : String; i : 1..kMaxStringLength; c : CHAR; uppercase : BOOLEAN; cI : INTEGER; PROCEDURE ReadString( VAR p : String ); BEGIN p.l := 0; REPEAT p.l := p.l + 1; READ( p.s[ p.l ] ) UNTIL EOLN OR ( p.l = kMaxStringLength ) END; PROCEDURE WriteString( p : String ); VAR i : 1..kMaxStringLength; BEGIN FOR i := 1 TO p.l DO WRITE( p.s[ i ] ) END; FUNCTION ToLowercase( p : CHAR ) : CHAR; VAR i : INTEGER; BEGIN IF p IN [ 'A'..'Z' ] THEN BEGIN i := ORD( p ) - ORD( 'A' ); i := i + ORD( 'a' ); p := CHR( i ) END; ToLowercase := p END; BEGIN WRITELN; WRITELN( '* ROT13 by graveborn' ); WRITELN( '* <http://thegraveborn.wordpress.com/>' ); WRITELN( '***' ); WRITELN( '* Enter a string to ROT13 and press the Return key;' ); WRITELN( '* or enter nothing and press the Return key to quit.' ); WRITELN( '***' ); WRITELN; WRITE( ' :' ); ReadString( gS ); WHILE gS.l > 1 DO BEGIN FOR i := 1 TO gS.l DO BEGIN c := gS.s[ i ]; uppercase := c IN [ 'A'..'Z' ]; c := ToLowercase( c ); IF c IN [ 'a'..'z' ] THEN BEGIN cI := ORD( c ) - ORD( 'a' ); cI := cI + 1; (* ^ So 'a' = 1, not 0 *) cI := cI + 13; IF cI > 26 THEN cI := cI - 26; cI := cI - 1; (* ^ So 'a' = 0, not 1 *) IF NOT uppercase THEN cI := cI + ORD( 'a' ) ELSE cI := cI + ORD( 'A' ); c := CHR( cI ) END; WRITE( c ) END; WRITELN; WRITE( ' :'); ReadString( gS ) END END.[…] Reblogged from Programming Praxis: […]
[…] following is the source code to my solution to the 6th problem – “ROT13: A simple Caesar-shift cipher” – of Programming Praxis, and my first program for the […]
Sorry for double post i’m trying to highlight my code correctly
My C++ version:
My C++ version:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
void getUserInput(string &strUserInput)
{
cout<< "Enter your text: " << endl;
getline(cin, strUserInput);
}
void ROT13(string &strUserInput, string &strResult)
{
for (auto it = strUserInput.begin(); it != strUserInput.end(); ++it)
{
if (isspace(*it) || ispunct(*it))
strResult += *it;
else
{
if (isupper(*it))
{
if (*it + 13 <= ‘Z’)
strResult += (*it + 13);
else
strResult += (*it – 13);
}
else
{
if (*it + 13 <= ‘z’)
strResult += (*it + 13);
else
strResult += (*it – 13);
}
}
}
}
int main()
{
string strUserInput, strResult;
getUserInput(strUserInput);
ROT13(strUserInput, strResult);
cout<< "The result text is: " << strResult << endl;
cin.get();
return 0;
}
My small version in C++ :
#include
std::string Rot13(std::string Input)
{
int i;
for(i=0; i = 65 && Input[i] = 97 && Input[i] = 78 && Input[i] = 110 && Input[i] <= 122))
Input[i] -= 13;
}
return Input;
}
Learning to Scala! A copy off of my worksheet:
object Rot { def rot13( text: String ): String = { val uppercase = new Range( 65, 90, 1 ) val lowercase = new Range( 97, 122, 1 ) def modAdd( a: Int, b: Int, max: Int, size: Int ): Int = if( (a + b) > max ) a+b-size else (a+b) def iter( in: String, acc: String ): String = if( in.isEmpty ) acc else if ( uppercase.contains(in.charAt(0)) ) iter( in.substring(1), acc+modAdd( in.charAt(0).toInt, 13, 90, 26).toChar ) else if ( lowercase.contains(in.charAt(0)) ) iter( in.substring(1), acc+modAdd( in.charAt(0).toInt, 13, 122, 26).toChar ) else iter( in.substring(1), acc+in.charAt(0) ) iter( text, "" ) } //> rot13: (text: String)String rot13(rot13("THISIS A TEST!!!")) //> res0: String = THISIS A TEST!!! rot13("HEYHEYHEYHEY") //> res1: String = URLURLURLURL rot13("!!!@@#!@") //> res2: String = !!!@@#!@ }#——————————————————————————-
# Name: Ceaser Cipher
# Author: Mrinal Wahal
# Created: 19/08/2014
# Copyright: (c) Mrinal 2014
#——————————————————————————-
alphas = {}
bets = ‘abcdefghijklmnopqrstuvwxyz’
string = raw_input(“Enter Your String Here – “)
print “NOTE – Value 0 Will Assign Default Rotation of 13 Places.”
rotation = input(“Rotation Should Take Place By – “)
num = 0
for letter in bets:
num += 1
alphas[letter]=num
def encrypt(string,rotation):
encrypted = “”
for let in string:
if rotation == 0:
rotation = 13
newvalue = alphas[let] + rotation
if newvalue > 26:
newvalue -= 26
for key in alphas.iterkeys():
if alphas[key] == newvalue:
print key,
encrypted += key
return encrypted
print “The Encrypted String is :”
en = encrypt(string,rotation)
def decrypt(dstring,drotation):
for dlet in str(dstring):
if drotation == 0:
drotation = 13
dnewvalue = alphas[dlet] – drotation
if dnewvalue < 0:
dnewvalue += 26
for dkey in alphas.iterkeys():
if alphas[dkey] == dnewvalue:
print dkey,
print "\nThe Decrypted String is :"
decrypt(en,rotation)
I think using C++11/14 makes for a very concise solution.
#include “Praxis006.hpp”
#include
#include
#include
// We can take advantage of RVO since rot13 is reversible
std::string rot13(std::string& line) {
std::transform(line.begin(), line.end(), line.begin(), [](char c) -> char {
if(not isalpha(c))
return c;
const char pivot = isupper(c) ? ‘A’ : ‘a’;
return (c – pivot + 13) % 26 + pivot;
});
return line;
}
void Praxis006() {
std::fstream f(“Rot13.txt”);
std::string line;
if(f.is_open()) {
std::getline(f, line);
rot13(line);
std::cout << line << std::endl;
}
}
February 20th, 2009.c:
#include "seal_bool.h" /* <http://GitHub.com/sealfin/C-and-C-Plus-Plus/blob/master/seal_bool.h> */ #include <ctype.h> #include <stdlib.h> #include <stdio.h> #include <string.h> char f_ROT13Character( const char p ) { if( !isalpha( p )) return p; else { const bool uppercase = isupper( p ); int i = p; if( uppercase ) i = tolower( i ); i -= 'a'; i += 13; if( i > 25 ) i -= 26; i += 'a'; if( uppercase ) i = toupper( i ); return ( char )i; } } #ifdef __MWERKS__ char *f_ReadString( void ) { char c, *string = ( char* )malloc( sizeof( char )); size_t length_of_string = 1; do { scanf( "%c", &c ); if( c != '\n' ) { string[ length_of_string - 1 ] = c; length_of_string ++; string = ( char* )realloc( string, sizeof( char ) * length_of_string ); } } while( c != '\n' ); string[ length_of_string - 1 ] = '\0'; return string; } #endif int main( const int argc, const char * const argv[] ) { #ifndef __MWERKS__ const size_t index = #ifdef LEONARDO 0 #else 1 #endif ; size_t i = index; #ifndef LEONARDO printf( "\n" ); #endif if( argc < index + 1 ) { printf( "This program must be passed, via the command line, a string; this program will then translate that string to- or from- ROT13.\n" ); #ifndef LEONARDO printf( "\n" ); #endif exit( EXIT_FAILURE ); } for( ; i < argc; i ++ ) { size_t k = 0; if( i > index ) printf( " " ); for( ; k < strlen( argv[ i ] ); k ++ ) printf( "%c", f_ROT13Character( argv[ i ][ k ] )); } printf( "\n" ); #ifndef LEONARDO printf( "\n" ); #endif #else char *string; bool error_occurred; size_t i = 0; do { printf( "Please enter a string; this program will then translate that string to- or from- ROT13.\n\n" ); printf( "Your input: " ); string = f_ReadString(); printf( "\n" ); if( strlen( string ) == 0 ) { free( string ); error_occurred = true; printf( "Sorry, an error occurred: you did not enter a string.\n\n" ); printf( "Please press the Return key to try again." ); free( f_ReadString()); printf( "\n" ); } else error_occurred = false; } while( error_occurred ); for( ; i < strlen( string ); i ++ ) printf( "%c", f_ROT13Character( string[ i ] )); free( string ); printf( "\n\n" ); printf( "This program will now quit.\n" ); #endif exit( EXIT_SUCCESS ); }The meaning of
“Cebtenzzvat Cenkvf vf sha!”is“Programming Praxis is fun!”The solution is known to run on an Apple Power Mac G4 (AGP Graphics) (450MHz processor, 1GB memory) on both Mac OS 9.2.2 (International English) (the solution interpreted using Leonardo IDE 3.4.1 and compiled using Metrowerks CodeWarrior IDE 2.1 (Discover Programming Edition)) and Mac OS X 10.4.11 (the solution compiled using the command line:
gcc seal_bool.h February\ 20th\,\ 2009.c -o February\ 20th\,\ 2009).(I’m just trying to solve the problems posed by this ‘site whilst I try to get a job; I’m well-aware that my solutions are far from the best – but, in my defence, I don’t have any traditional qualifications in computer science :/ )
Ps. It’s a little early, but merry Christmas, and thank you for running this ‘site!
Answer:
Programming Praxis is fun!