Created
September 4, 2013 15:59
-
-
Save flc/6439105 to your computer and use it in GitHub Desktop.
A Tour of Go - Exercise: Rot13 Reader
http://tour.golang.org/#61
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
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) | |
} |
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)
}
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)
}
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)
}
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)
}
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)
}
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!
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)
}
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)
}
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)
}
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)
}
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)
}
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
}
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)
}
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
Use a switch to make the code clearer.