Skip to content

Instantly share code, notes, and snippets.

@flc
Created September 4, 2013 15:59
Show Gist options
  • Save flc/6439105 to your computer and use it in GitHub Desktop.
Save flc/6439105 to your computer and use it in GitHub Desktop.
A Tour of Go - Exercise: Rot13 Reader http://tour.golang.org/#61
package main
import (
"io"
"os"
"strings"
//"fmt"
"bytes"
)
var ascii_uppercase = []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
var ascii_lowercase = []byte("abcdefghijklmnopqrstuvwxyz")
var ascii_uppercase_len = len(ascii_uppercase)
var ascii_lowercase_len = len(ascii_lowercase)
type rot13Reader struct {
r io.Reader
}
func rot13(b byte) byte {
pos := bytes.IndexByte(ascii_uppercase, b)
if pos != -1 {
return ascii_uppercase[(pos+13) % ascii_uppercase_len]
}
pos = bytes.IndexByte(ascii_lowercase, b)
if pos != -1 {
return ascii_lowercase[(pos+13) % ascii_lowercase_len]
}
return b
}
func (r rot13Reader) Read(p []byte) (n int, err error) {
n, err = r.r.Read(p)
for i := 0; i < n; i++ {
p[i] = rot13(p[i])
}
return n, err
}
func main() {
s := strings.NewReader(
"Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
@ptagr
Copy link

ptagr commented May 25, 2018


import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (pr rot13Reader) Read(bytes []byte) (n int, err error) {
	n, err = pr.r.Read(bytes)
	for i,_ := range bytes {
		if bytes[i] >= 97 && bytes[i] <= 122 {
			bytes[i] = byte((bytes[i] - 97 + 13) % 26 + 97)
		} else if bytes[i] >= 65 && bytes[i] <= 90 {
			bytes[i] = byte((bytes[i] - 65 + 13) % 26 + 65)
		}
	}
	return n,err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@justinpage
Copy link

Had some fun using maps and relying on byte conversion:

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (reader rot13Reader) Read(p []byte) (int, error) {
	n, err := reader.r.Read(p)

	if err == io.EOF {
		return 0, err
	}

	lookup := map[string]string{
		"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", "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",
	}

	for index := range p[:n] {
		code := lookup[string(p[index])]

		if code != "" {
			p[index] = []byte(code)[0]
		}
	}

	return len(p), nil
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@gothicx
Copy link

gothicx commented Aug 14, 2018

// Another version of rot13

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func rot13(b byte) byte {
	if b >= 'A' && b <= 'M' || b >= 'a' && b <= 'm' {
		return b + 13
	}
	if b > 'M' && b <= 'Z' || b > 'm' && b <= 'z' {
		return b - 13
	}
	return b
}

func (rot rot13Reader) Read(b []byte) (int, error) {
	n, err := rot.r.Read(b)
	
	for i := range b {
		b[i] = rot13(b[i])
	}

	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@xtttttttttx
Copy link

xtttttttttx commented Sep 10, 2018

Use a switch to make the code clearer.

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read(b []byte) (int, error) {
	n, _ := rot.r.Read(b)
	for i := 0; i < n; i++ {
		switch {
		case b[i] + 13 > 'z':
			b[i] -= 13
		case b[i] > 'a':
			b[i] += 13
		case b[i] + 13 > 'Z':
			b[i] -= 13
		case b[i] > 'A':
			b[i] += 13
		}
	}
	return n, nil
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@kden416
Copy link

kden416 commented Jan 19, 2019

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read(b []byte) (int, error) {
	ln, err := rot.r.Read(b)
	for i := 0; i < ln; i++ {
		switch {
		case b[i] >= 65 && b[i] <= 77:
			b[i] += 13
		case b[i] >= 78 && b[i] <= 90:
			b[i] -= 13
		case b[i] >= 97 && b[i] <= 109:
			b[i] += 13
		case b[i] >= 110 && b[i] <= 122:
			b[i] -= 13
		}
	}
	return ln, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@danx12
Copy link

danx12 commented Mar 9, 2019

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read(b []byte) (int, error) {

	n, err := rot.r.Read(b)
	for i := range b {
		if b[i] >= 0x41 && b[i] <= 0x5a {
			b[i] = byte((int(b[i]) - 0x41 + 13 )% 26 + 0x41)
		} else if b[i] >= 0x61 && b[i] <= 0x7a {
			b[i] = byte((int(b[i]) - 0x61 + 13 )% 26 + 0x61)
		}
	}

	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@metatronz
Copy link

metatronz commented Sep 13, 2019

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read(p []byte) (n int, err error) {

	var rmap = map[byte]byte{65: 78, 66: 79, 67: 80, 68: 81, 69: 82, 70: 83,
		71: 84, 72: 85, 73: 86, 74: 87, 75: 88, 76: 89, 77: 90,
		78: 65, 79: 66, 80: 67, 81: 68, 82: 69, 83: 70, 84: 71,
		85: 72, 86: 73, 87: 74, 88: 75, 89: 76, 90: 77, 97: 110,
		98: 111, 99: 112, 100: 113, 101: 114, 102: 115, 103: 116,
		104: 117, 105: 118, 106: 119, 107: 120, 108: 121, 109: 122,
		110: 97, 111: 98, 112: 99, 113: 100, 114: 101, 115: 102, 116: 103,
		117: 104, 118: 105, 119: 106, 120: 107, 121: 108, 122: 109}
	if n, err = rot.r.Read(p); err == nil {
		for x, src := range p {
			if dst, ok := rmap[src]; ok {
				p[x] = dst
			}
		}
	}
	return
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@sometimesalready
Copy link

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (r rot13Reader) Read(b []byte) (int, error){
	n, e := r.r.Read(b)
	for i:=0; i<n; i++ {
		b[i] = byte(rot13(rune(b[i])))
	}
	return n, e
}


func rot13(r rune) rune {
    if r >= 'a' && r <= 'z' {
        // Rotate lowercase letters 13 places.
        if r >= 'm' {
            return r - 13
        } else {
            return r + 13
        }
    } else if r >= 'A' && r <= 'Z' {
        // Rotate uppercase letters 13 places.
        if r >= 'M' {
            return r - 13
        } else {
            return r + 13
        }
    }
    // Do nothing.
    return r
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@Maximilan4
Copy link

Maximilan4 commented Dec 11, 2019

package main

import (
    "io"
    "os"
    "strings"
)

type rot13Reader struct {
    r io.Reader
}

func (reader rot13Reader) Read(p []byte) (int, error) {
    n, err := reader.r.Read(p)
    if err != nil {
        return n, err
    }

    for index := 0; index <= n-1; index++ {
        value := p[index]
        if value < 65 || value > 122 {
            continue
        }

        if (value > 77 && value < 90) || value > 109 {
            p[index] -= 13
        } else {
            p[index] += 13
        }
    }

    return n, err
}

func main() {
    s := strings.NewReader("Lbh penpxrq gur pbqr!")
    r := rot13Reader{s}
    io.Copy(os.Stdout, &r)
}

@ur4nium235
Copy link

My solution

package main

import (
    "io"
    "os"
    "strings"
)

type rotReader struct {
	r io.Reader
}

func rotX(x byte, rot int) byte {
	if x >= 65 && x <= 90 {
		x = byte((int(x)-65+rot)%26 + 65)
	} else if x >= 97 && x <= 122 {
		x = byte((int(x)-97+rot)%26 + 97)
	}
	return x
}

func (rot rotReader) Read(b []byte) (int, error) {
	n, err := rot.r.Read(b)
	for i := range b {
		b[i] = rotX(b[i], 13)
	}
	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rotReader{s}
	io.Copy(os.Stdout, &r)
}

Output:
You cracked the code!

@hjalte33
Copy link

hjalte33 commented Feb 27, 2020

Came up with this little approach. The idea is to just try first by adding 13 and if we missed and went past z then just undo by subtracting 26. Thought it was a fun alternative

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot rot13Reader) Read(b []byte) (n int, err error) {
	n, err = rot.r.Read(b)
	if err != nil {
		return 0, err
	}
	for i := 0; i < n; i++ {
		b[i] += 13
		if b[i] > 'z' || (b[i] > 'Z' && b[i] < 'Z'+13) {
			b[i] -= 26
		}
	}
	return n, nil
}

func main() {
	s := strings.NewReader("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@this-is-richard
Copy link

package main

import (
	"io"
	"os"
	"strings"
	//"fmt"
)

type rot13Reader struct {
	r io.Reader
}

func (rot13 rot13Reader) Read(b []byte) (int, error) {
	n, err := rot13.r.Read(b)
	for i := 0; i < n; i++ {
		switch {
			case b[i] >= 65 && b[i] <= 90:
				if b[i] <= 77 { b[i] = b[i] + 13 } else { b[i] = b[i] - 13 }
			case b[i] >= 97 && b[i] <= 122:
				if b[i] <= 109 { b[i] = b[i] + 13 } else { b[i] = b[i] - 13 }
		}
    }
	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@olehcambel
Copy link

olehcambel commented Apr 14, 2020

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (rot13 rot13Reader) Read(p []byte) (int, error) {
	input := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
	output := "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"

	n, err := rot13.r.Read(p)

	for i := 0; i < n; i++ {
		index := strings.Index(input, string(p[i]))

		if index != -1 {
			p[i] = output[index]
		}
	}

	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@kaen98
Copy link

kaen98 commented Apr 28, 2020

package main

import (
	"io"
	"os"
	"strings"
)

const src string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
const des string = "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"

type rot13Reader struct {
	r io.Reader
}

func (rot13 rot13Reader) Read(bytes []byte) (int, error) {
	len, err := rot13.r.Read(bytes)
	for i, v := range bytes {
		index := strings.IndexByte(src, v)
		if (index != -1) {
			bytes[i] = des[index]
		}
	}
	return len, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@hashlash
Copy link

https://gist.github.com/hashlash/63edd5ab69cafe6ef762023e1cacc7ef

package main

import (
    "io"
    "os"
    "strings"
)

type rot13Reader struct {
    r io.Reader
}

func (r13 rot13Reader) Read(b []byte) (int, error) {
    l, err := r13.r.Read(b)
    if err == nil {
        for i := range b {
            switch {
                case 'A' <= b[i] && b[i] <= 'Z':
                    b[i] = (b[i] - 'A' + 13) % 26 + 'A'
                case 'a' <= b[i] && b[i] <= 'z':
                    b[i] = (b[i] - 'a' + 13) % 26 + 'a'
            }
        }
    }
    return l, err
}

func main() {
    s := strings.NewReader("Lbh penpxrq gur pbqr!")
    r := rot13Reader{s}
    io.Copy(os.Stdout, &r)
}

@KunalKumarSwift
Copy link

KunalKumarSwift commented Sep 7, 2021

func (r rot13Reader) Read(b []byte) (n int, err error) {
	// read incoming stream and get length and error
	n, err = r.r.Read(b)
	// iterate over that range and read individual byte element
	for i := 0; i < n; i++ {
		v := b[i]
		// check ascii codes and keep replacing in the original stream b
		if v >= 65 && v <= 77 {
			b[i] = v + 13
		}

		if v >= 78 && v <= 90 {
			b[i] = v - 13
		}

		if v >= 97 && v <= 109 {
			b[i] = v + 13
		}

		if v >= 110 && v <= 122 {
			b[i] = v - 13
		}
	}
        if err == io.EOF {
		return 0, err
	}
	return n, nil
}

@C-Canchola
Copy link

C-Canchola commented Oct 3, 2021

Saw this on wikipedia and wanted to see if I could implement the Read method using it:
$ # Map upper case A-Z to N-ZA-M and lower case a-z to n-za-m
$ tr 'A-Za-z' 'N-ZA-Mn-za-m' <<< "The Quick Brown Fox Jumps Over The Lazy Dog"
Gur Dhvpx Oebja Sbk Whzcf Bire Gur Ynml Qbt

My attempt:

package main

import (
	"bytes"
	"io"
	"os"
	"os/exec"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

// trRot returns a new byte slice by using the tr command on the originally provided byte slice.
func trRot(b []byte) ([]byte, error) {

	r13Buf := &bytes.Buffer{}

	cmd := exec.Command("tr", "A-Za-z", "N-ZA-Mn-za-m")
	cmd.Stdin, cmd.Stdout, cmd.Stderr = bytes.NewBuffer(b), r13Buf, os.Stderr

	if err := cmd.Run(); err != nil {
		return nil, err
	}

	return r13Buf.Bytes(), nil
}

func (rr rot13Reader) Read(b []byte) (int, error) {

	readBytes := make([]byte, len(b))

	n, err := rr.r.Read(readBytes)
	if err != nil {
		return n, err
	}

	r13Bytes, err := trRot(readBytes)
	if err != nil {
		return 0, err
	}

	return copy(b, r13Bytes), err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

@Spaider
Copy link

Spaider commented Jun 7, 2022

Hey, looks like almost nobody noticed that there's an exclamation mark at the end of the string :)

package main

import (
	"io"
	"os"
	"strings"
)

type rot13Reader struct {
	r io.Reader
}

func (r13 rot13Reader) Read(p []byte) (int, error) {
	var n, err = r13.r.Read(p)

	for i := 0; i < n; i++ {
		var inp = p[i]
		if (inp >= 65 && inp <= 77) ||
			(inp >= 97 && inp <= 109) {
			p[i] = inp + 13
		} else if (inp >= 78 && inp <= 90) ||
			(inp >= 110 && inp <= 122) {
			p[i] = inp - 13
		}
	}

	return n, err
}

func main() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment