Go语言之旅练习#23:rot13Reader

huangapple go评论85阅读模式
英文:

Tour of Go exercise #23: rot13Reader

问题

我正在尝试解决Go之旅中的练习rot13Reader

这是我的解决方案:

package main

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

type rot13Reader struct {
	r io.Reader
}

func rot13(x byte) byte {
	switch {
	case x >= 65 && x <= 77:
		fallthrough
	case x >= 97 && x <= 109:
		x = x + 13
	case x >= 78 && x <= 90:
		fallthrough
	case x >= 110 && x >= 122:
		x = x - 13
	}
	return x
}

func (r13 *rot13Reader) Read(b []byte) (int, error) {
	n, err := r13.r.Read(b)
	for i := 0; i <= n; i++ {
		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)
}

它返回You prnpxrq tur poqr!,这意味着只有"Lbh penpxrq gur pbqr!"的第一个单词被解密了。我如何解密整个句子?

英文:

I'm trying to solve the Tour of Go exercise rot13Reader:

Here is my solution:

package main

import (
	&quot;io&quot;
	&quot;os&quot;
	&quot;strings&quot;
)

type rot13Reader struct {
	r io.Reader
}

func rot13(x byte) byte {
	switch {
	case x &gt;= 65 &amp;&amp; x &lt;= 77:
		fallthrough
	case x &gt;= 97 &amp;&amp; x &lt;= 109:
		x = x + 13
	case x &gt;= 78 &amp;&amp; x &lt;= 90:
		fallthrough
	case x &gt;= 110 &amp;&amp; x &gt;= 122:
		x = x - 13
	}
	return x
}

func (r13 *rot13Reader) Read(b []byte) (int, error) {
	n, err := r13.r.Read(b)
	for i := 0; i &lt;= n; i++ {
		b[i] = rot13(b[i])
	}
	return n, err
}

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

It returns You prnpxrq tur poqr!, that means only the first word of "Lbh penpxrq gur pbqr!" is cracked. How can I crack the whole sentence?

答案1

得分: 29

编辑:

基本上你的解决方案是好的并且有效,只是你打错了一个字符:

case x &gt;= 110 &amp;&amp; x &gt;= 122:

将其改为:

case x &gt;= 110 &amp;&amp; x &lt;= 122:

你的输入和输出:

Lbh penpxrq gur pbqr!
You prnpxrq tur poqr!

每个单词都发生了变化。问题不仅仅是只有第一个单词被读取和解码,问题在于你的解码算法。

ROT13 中,如果移位超出字母范围,你必须从字母表的开头(或末尾)重新开始。例如,将 &#39;N&#39; 移位为 &#39;Z&#39; + 1,所以它变成了第一个字母 &#39;A&#39;。看看这个简单的字符映射:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm

所以你应该在移位 13 之后,如果字母超出了字母表,将其移位 -26(英文字母的数量),这样就能达到期望的效果(在最后一个字母之后,你从第一个字母继续)。

一个示例解决方案:

func rot13(x byte) byte {
    capital := x &gt;= &#39;A&#39; &amp;&amp; x &lt;= &#39;Z&#39;
    if !capital &amp;&amp; (x &lt; &#39;a&#39; || x &gt; &#39;z&#39;) {
        return x // 不是字母
    }

    x += 13
    if capital &amp;&amp; x &gt; &#39;Z&#39; || !capital &amp;&amp; x &gt; &#39;z&#39; {
        x -= 26
    }
    return x
}

它的输出是:

You cracked the code!

Go Playground 上试一试。

英文:

EDIT:

Basically your solution is good and works, you just mistyped 1 character:

case x &gt;= 110 &amp;&amp; x &gt;= 122:

Change it to:

case x &gt;= 110 &amp;&amp; x &lt;= 122:

Your input and output:

Lbh penpxrq gur pbqr!
You prnpxrq tur poqr!

There is change in every word. The problem is not that only the first word is read and decoded, the problem is in your decoding algorithm.

In ROT13 if shifting goes outside of the letter range, you have to start from the beginning of the alphabet (or at the end). For example shifting &#39;N&#39; would be &#39;Z&#39; + 1, so it becomes &#39;A&#39;, the first letter. See this simple character mapping:

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm

So what you should do is after shifting by 13, if the letter goes outside of the alphabet, shift it by -26 (number of letters in the English alphabet) which has the desired effect (that after the last letter you continued from the first).

An example solution:

func rot13(x byte) byte {
	capital := x &gt;= &#39;A&#39; &amp;&amp; x &lt;= &#39;Z&#39;
	if !capital &amp;&amp; (x &lt; &#39;a&#39; || x &gt; &#39;z&#39;) {
		return x // Not a letter
	}

	x += 13
	if capital &amp;&amp; x &gt; &#39;Z&#39; || !capital &amp;&amp; x &gt; &#39;z&#39; {
		x -= 26
	}
	return x
}

And its output:

You cracked the code!

Try it on the Go Playground.

答案2

得分: 9

你也可以使用以下代码替代:

func rot13(x byte) byte {
    input := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
    output := []byte("NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm")
    match := bytes.Index(input, []byte{x})
    if match == -1 {
        return x
    }
    return output[match]
}

这段代码是一个用于实现 ROT13 加密算法的函数。它将输入的字节 x 映射为 ROT13 加密后的字节。如果输入的字节不在映射表中,则直接返回原始字节。

英文:

You could also use instead:

func rot13(x byte) byte {
    input := []byte(&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;)
    output := []byte(&quot;NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm&quot;)
    match := bytes.Index(input, []byte{x})
    if match == -1 {
	    return x
    }
    return output[match]
}

答案3

得分: 3

我更喜欢在rot13函数中直接操作整数。

package main

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

type rot13Reader struct {
	r io.Reader
}

const a int = int('a')
const z int = int('z')

const A int = int('A')
const Z int = int('Z')

func rot13(b int) int {

	isLower := b >= a && b <= z
	isUpper := b >= A && b <= Z

	if isLower {
		return a + ((b - a + 13) % 26)
	}

	if isUpper {
		return A + ((b - A + 13) % 26)
	}

	return b
}

func (rot *rot13Reader) Read(b []byte) (int, error) {
	n, err := rot.r.Read(b)
	if err == io.EOF {
		return 0, err
	}

	for x := range b {
		b[x] = byte(rot13(int(b[x])))
	}
	return n, err
}

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

以上是要翻译的内容。

英文:

I prefer manipulate directly integers in rot13 function

package main

import (
	&quot;io&quot;
	&quot;os&quot;
	&quot;strings&quot;
)

type rot13Reader struct {
	r io.Reader
}

const a int = int(&#39;a&#39;)
const z int = int(&#39;z&#39;)

const A int = int(&#39;A&#39;)
const Z int = int(&#39;Z&#39;)

func rot13(b int) int {

	isLower := b &gt;= a &amp;&amp; b &lt;= z
	isUpper := b &gt;= A &amp;&amp; b &lt;= Z

	if isLower {
		return a + ((b - a + 13) % 26)
	}

	if isUpper {
		return A + ((b - A + 13) % 26)
	}

	return b
}

func (rot *rot13Reader) Read(b []byte) (int, error) {
	n, err := rot.r.Read(b)
	if err == io.EOF {
		return 0, err
	}

	for x := range b {
		b[x] = byte(rot13(int(b[x])))
	}
	return n, err
}

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

答案4

得分: 3

func (reader rot13Reader) Read(bytes []byte) (int, error) {
    n, err := reader.r.Read(bytes)
    for i, val := range bytes[:n] {
        if val >= 'a' && val <= 'z' {
            bytes[i] = (val-'a'+13)%26 + 'a'
        } else if val >= 'A' && val <= 'Z' {
            bytes[i] = (val-'A'+13)%26 + 'A'
        }
    }
    return n, err
}

这段代码是一个实现了 ROT13 编码的读取器。它接收一个字节数组作为输入,并对其中的字母进行 ROT13 编码。ROT13 编码是一种简单的字母替换加密方法,将字母表中的每个字母替换为字母表中它后面第 13 个字母。对于小写字母,替换后的字母仍为小写字母;对于大写字母,替换后的字母仍为大写字母。其他非字母字符保持不变。函数返回读取的字节数和可能出现的错误。

英文:
func (reader rot13Reader) Read(bytes []byte) (int, error) {
	n, err := reader.r.Read(bytes)
	for i, val := range bytes[:n] {
		if val &gt;= &#39;a&#39; &amp;&amp; val &lt;= &#39;z&#39; {
			bytes[i] = (val-&#39;a&#39;+13)%26 + &#39;a&#39;
		} else if val &gt;= &#39;A&#39; &amp;&amp; val &lt;= &#39;Z&#39; {
			bytes[i] = (val-&#39;A&#39;+13)%26 + &#39;A&#39;
		}
	}
	return n, err
}

答案5

得分: 2

问题在于你的函数不按照你的期望工作。为了验证这一点,只需尝试在"Lbh penpxrq Lbh gur pbqr!"上运行你的函数。如你所见,第一个单词被解码了(以及第三个单词)。这意味着你的函数不仅仅在第一个单词上运行,实际上它在所有单词上都运行了(只是碰巧没有其他内容被改变)。

func (rot *rot13Reader) Read(p []byte) (n int, err error) {
    n, err = rot.r.Read(p)
    for i := 0; i < len(p); i++ {
        if (p[i] >= 'A' && p[i] < 'N') || (p[i] >= 'a' && p[i] < 'n') {
            p[i] += 13
        } else if (p[i] > 'M' && p[i] <= 'Z') || (p[i] > 'm' && p[i] <= 'z'){
            p[i] -= 13
        }
    }
    return
}

这里是一个Playground。代码取自这里

英文:

The problem is that your function does not work as you want. To verify this, just try to run your function on &quot;Lbh penpxrq Lbh gur pbqr!&quot;. As you see first word is decoded (as well as the third one). So this means that your function does not run only on the first word, but in fact runs on all the words (it just happened that nothing else is changed).

func (rot *rot13Reader) Read(p []byte) (n int, err error) {
	n, err = rot.r.Read(p)
	for i := 0; i &lt; len(p); i++ {
		if (p[i] &gt;= &#39;A&#39; &amp;&amp; p[i] &lt; &#39;N&#39;) || (p[i] &gt;=&#39;a&#39; &amp;&amp; p[i] &lt; &#39;n&#39;) {
			p[i] += 13
		} else if (p[i] &gt; &#39;M&#39; &amp;&amp; p[i] &lt;= &#39;Z&#39;) || (p[i] &gt; &#39;m&#39; &amp;&amp; p[i] &lt;= &#39;z&#39;){
			p[i] -= 13
		}
	}
	return
}

And here is a <kbd>Playground</kbd>. Code is taken from here.

答案6

得分: 2

我的代码也可以运行,而且更简单!

func (rd *rot13Reader) Read(b []byte) (int, error) {
    m := make(map[byte]byte)
    input := "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
    output := "NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm"
    for idx := range input {
        m[input[idx]] = output[idx]
    }

    n, err := rd.r.Read(b)
    for i := 0; i < n; i++ {
        if val, ok := m[b[i]]; ok {
            b[i] = val
        }
    }
    return n, err
}
英文:

My code also works, it's more simple!

func (rd *rot13Reader) Read(b []byte) (int, error) {
	m := make(map[byte]byte)
	input := &quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;
	output := &quot;NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm&quot;
	for idx := range input {
		m[input[idx]] = output[idx]
	}

	n, err := rd.r.Read(b)
	for i := 0; i &lt; n; i++ {
	    if val, ok := m[b[i]]; ok {
		  b[i] = val
	    }
	}
	return n, err
}

答案7

得分: 2

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)
	if err == io.EOF {
		return 0, err
	}

	for i := range b {
		var base byte
		if b[i] >= 'a' && b[i] <= 'z' {
			base = 'a'
		} else if b[i] >= 'A' && b[i] <= 'Z' {
			base = 'A'
		} else {
			continue
		}
		b[i] = (((b[i] - base) + 13) % 26) + base
	}
	return n, err
}

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

这是一个使用Go语言编写的程序,它实现了一个rot13Reader类型,用于对输入进行ROT13加密解密。在main函数中,创建了一个字符串读取器s,并将其传递给rot13Reader类型的r。然后,使用io.Copy函数将r的输出复制到标准输出(os.Stdout)。程序的输出结果是"Lbh penpxrq gur pbqr!"。

英文:
package main

import (
	&quot;io&quot;
	&quot;os&quot;
	&quot;strings&quot;
)

type rot13Reader struct {
	r io.Reader
}

func (rot *rot13Reader) Read(b []byte) (int, error) {
	n, err := rot.r.Read(b)
	if err == io.EOF {
		return 0, err
	}

	for i := range b {
		var base byte
		if b[i] &gt;= &#39;a&#39; &amp;&amp; b[i] &lt;= &#39;z&#39; {
			base = &#39;a&#39;
		} else if b[i] &gt;= &#39;A&#39; &amp;&amp; b[i] &lt;= &#39;Z&#39; {
			base = &#39;A&#39;
		} else {
			continue
		}
		b[i] = (((b[i] - base) + 13) % 26) + base
	}
	return n, err
}

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

答案8

得分: 1

作为对@icza答案的跟进,不要硬编码检查字节是否为字母,而是创建一个小函数来确定它。这样可以使代码更清晰。

func alphabetic(x byte) bool {
    return (x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z')
}

func capital(x byte) bool {
    return x >= 'A' && x <= 'Z'
}

func rot13(x byte) byte {
    // 字节不是字母
    if !alphabetic(x) {
        return x
    }

    original_is_capital := capital(x)

    // 应用 rot13
    x += 13

    // 新字母应该循环
    if !alphabetic(x) || original_is_capital {
        x -= 26
    }

    return x
}
英文:

As a follow up to the answer by @icza, rather than hard-coding the checks for whether the byte is alphabetic or not, create a small function to determine it instead. It makes for much cleaner code.

func alphabetic(x byte) bool {
return (x &gt;= &#39;A&#39; &amp;&amp; x &lt;=&#39;Z&#39;) || (x &gt;= &#39;a&#39; &amp;&amp; x &lt;= &#39;z&#39;)
}
func capital(x byte) bool {
return x &gt;= &#39;A&#39; &amp;&amp; x &lt;= &#39;Z&#39;
}
func rot13(x byte) byte {
// byte isn&#39;t a letter
if !alphabetic(x) {
return x
}
original_is_capital := capital(x)
// apply rot13  
x += 13
// the new letter should loop around
if !alphabetic(x) || original_is_capital {
x -= 26
}
return x
}

答案9

得分: 1

func rot13(x byte) byte {
    if (x >= 'A' && x <= 'M') || (x >= 'a' && x <= 'm') {
        return x + 13
    } else if (x >= 'N' && x <= 'Z') || (x >= 'n' && x <= 'z') {
        return x - 13
    } else {
        return x
    }
}
func rot13(x byte) byte {
    if (x >= 'A' && x <= 'M') || (x >= 'a' && x <= 'm') {
        return x + 13
    } else if (x >= 'N' && x <= 'Z') || (x >= 'n' && x <= 'z') {
        return x - 13
    } else {
        return x
    }
}
英文:
func rot13(x byte) byte {
if (x &gt;=  &#39;A&#39; &amp;&amp; x &lt;= &#39;M&#39;) || (x &gt;=  &#39;a&#39; &amp;&amp; x &lt;= &#39;m&#39;) {
return x + 13
} else if (x &gt;=  &#39;N&#39; &amp;&amp; x &lt;= &#39;Z&#39;) || (x &gt;=  &#39;n&#39; &amp;&amp; x &lt;= &#39;z&#39;) {
return x - 13
} else {
return x
}
}

答案10

得分: 0

一个简单的代码片段,它会改变字母并忽略其他字符。

func (rot *rot13Reader) Read(b []byte) (int, error) {
    size, e := rot.r.Read(b)
    for i := 0; i < size; i++ {
        if b[i] < byte('A') || b[i] > byte('z') {
            continue
        }
        if b[i] > byte('a') {
            b[i] = byte('a') + (b[i] - byte('a') + 13) % 26
        } else {
            b[i] = byte('A') + (b[i] - byte('A') + 13) % 26
        }
    }
    return size, e
}

这段代码会将字母进行改变,忽略其他字符。它使用了 ROT13 加密算法,将字母按照一定规则进行替换。具体来说,大写字母会被替换成字母表中往后数第 13 个字母的大写形式,小写字母会被替换成字母表中往后数第 13 个字母的小写形式。其他字符不受影响。函数的返回值为读取的字节数和可能的错误。

英文:

A simple code snippet that changes alphabets and ignores other characters

func (rot *rot13Reader) Read(b [] byte) (int, error) {
size,e := rot.r.Read(b)
for i := 0; i &lt; size; i++ {
if b[i] &lt; byte(&#39;A&#39;) || b[i] &gt; byte(&#39;z&#39;) {
continue
}
if b[i] &gt; byte(&#39;a&#39;) {
b[i] = byte(&#39;a&#39;) + (b[i] - byte(&#39;a&#39;) + 13)%26
} else {
b[i] = byte(&#39;A&#39;) + (b[i] - byte(&#39;A&#39;) + 13)%26
}
}
return size, e
}

答案11

得分: 0

以下是翻译好的内容:

我也要发表一点意见:

https://play.golang.org/p/1Wze47kL-bA

package main

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

type rot13Reader struct {
	r io.Reader
}

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

	if err != nil {
		return n, err
	}

	for i := 0; i < n; i++ {
		r := rune(buf[i])
		if !unicode.IsLetter(r) {
			continue
		}
		isUpper := unicode.IsUpper(r)
		r += 13
		if !unicode.IsLetter(r) || isUpper && r >= 'a' {
			r -= 26
		}
		buf[i] = byte(r)
	}
	return n, err
}

func ExampleRot13Reader() {
	s := strings.NewReader("Lbh penpxrq gur pbqr!")
	r := rot13Reader{s}
	io.Copy(os.Stdout, &r)
	// Output: You cracked the code!
}

准备好接受诸如“仅仅提供代码作为答案并不是很有帮助”之类的评论……这是一个特殊情况,提问者正在寻求其他解决方案,这是一种有趣的比较不同方法的方式。不需要解释太多。

英文:

Throwing my 2 cents in as well:

https://play.golang.org/p/1Wze47kL-bA

package main
import (
&quot;io&quot;
&quot;os&quot;
&quot;strings&quot;
&quot;unicode&quot;
)
type rot13Reader struct {
r io.Reader
}
func (r rot13Reader) Read(buf []byte) (int, error) {
n, err := r.r.Read(buf)
if err != nil {
return n, err
}
for i := 0; i &lt; n; i++ {
r := rune(buf[i])
if !unicode.IsLetter(r) {
continue
}
isUpper := unicode.IsUpper(r)
r += 13
if !unicode.IsLetter(r) || isUpper &amp;&amp; r &gt;= &#39;a&#39; {
r -= 26
}
buf[i] = byte(r)
}
return n, err
}
func ExampleRot13Reader() {
s := strings.NewReader(&quot;Lbh penpxrq gur pbqr!&quot;)
r := rot13Reader{s}
io.Copy(os.Stdout, &amp;r)
// Output: You cracked the code!
}

Preparing for comments such as "Simply providing code as an answer is not very helpful"... this is a special case where the questioner is asking for other solutions, and this is a fun way to compare various approaches. No need to really explain much.

答案12

得分: 0

我的尝试:

package main

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

const a byte = byte('a')
const n byte = byte('n')
const z byte = byte('z')

const A byte = byte('A')
const N byte = byte('N')
const Z byte = byte('Z')


type rot13Reader struct {
	r io.Reader
}

func rot13(b byte) byte {
	switch {
		case ((b >= A && b < N) || (b >= a && b < n)):
			b += 13
		case ((b >= N && b <= Z) || (b >= n && b <= z)):
			b -= 13
	}
	return b
}

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

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

一个简单而直观的方法 Go语言之旅练习#23:rot13Reader

英文:

My try:

package main

import (
	&quot;io&quot;
	&quot;os&quot;
	&quot;strings&quot;
)

const a byte = byte(&#39;a&#39;)
const n byte = byte(&#39;n&#39;)
const z byte = byte(&#39;z&#39;)

const A byte = byte(&#39;A&#39;)
const N byte = byte(&#39;N&#39;)
const Z byte = byte(&#39;Z&#39;)


type rot13Reader struct {
	r io.Reader
}

func rot13(b byte) byte {
	switch {
		case ((b &gt;= A &amp;&amp; b &lt; N) || (b &gt;= a &amp;&amp; b &lt; n)):
			b += 13
		case ((b &gt;= N &amp;&amp; b &lt;= Z) || (b &gt;= n &amp;&amp; b &lt;= z)):
			b -= 13
	}
	return b
}

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

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

A simple and intuitive approach Go语言之旅练习#23:rot13Reader

答案13

得分: 0

或者,如果你既不想使用地图,也不想使用其他人使用的花哨函数/运算符,你可以设置一个基于数组的翻译表,无需搜索。通过使用一个字节数组,将所有的rot13转换提前完成。

注意,翻译数组是以编程方式生成的示例,实际上,代码比下面的更容易阅读/交叉检查:

x := [256]byte{0, 1, 2,..., (rot13的较小值), ..., (rot13的较大值), ..., 255}

以下是代码示例:

package main

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

type rot13Reader struct {
	r        io.Reader
	r13array [256]byte
}

// 不要忘记使用*,否则它会在副本上执行所有的工作并将其丢弃
func (r *rot13Reader) initialize_r13() {
	// 在进行任何rot-13转换之前必须调用此函数
	var cap_A_offset int = int('A')
	var low_a_offset int = int('a')

	// 为了简单起见,初始化整个数组,索引=自身
	for c := 0; c < 256; c++ {
		r.r13array[c] = byte(c)
	}

	// 现在预先计算A-Z和a-z的rot-13值
	// 这些值将覆盖数组中的值
	for c := 0; c <= 26; c++ {
		rot_13 := (c + 13) % 26
		r.r13array[c+cap_A_offset] = byte(rot_13 + cap_A_offset)
		r.r13array[c+low_a_offset] = byte(rot_13 + low_a_offset)
	}
}

func (r rot13Reader) Read(b []byte) (int, error) {
	numread, e := r.r.Read(b)
	if e == nil {
		for i := 0; i < numread; i += 1 {
			c := r.r13array[b[i]]
			// 在设置之前,没有必要执行类似于“if in != out”的操作
			// 我怀疑那样甚至可能更慢。
			b[i] = c
		}
	}
	return numread, e
}

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

以上是代码的翻译部分。

英文:

Or, if you neither want to use maps nor those fancy-schmancy functions/operators other folks are using, you can set up an array-based translation table that needs no searching. Trick it to have all the rot13-ing be done ahead of time by using an array of bytes where the index has the rot-13'd value.

Note that the translation array is programmatically generated as an example, and frankly, the code is easier to read / crosscheck than:

x = [256]byte{0, 1, 2,..., (lower rot13 values), ..., (upper...), ...,255}

Code as below

package main
import (
&quot;io&quot;
&quot;os&quot;
&quot;strings&quot;
)
type rot13Reader struct {
r io.Reader
r13array [256]byte
}
// Don&#39;t forget the *, or it will do all the work on a copy and throw
// it away
func (r *rot13Reader) initialize_r13() {
// Must be called before doing any rot-13-ing
var cap_A_offset int = int(&#39;A&#39;)
var low_a_offset int = int(&#39;a&#39;)
// For simplicity&#39;s sake, initialize the entire array, index=itself
for c := 0; c &lt; 256; c++ {
r.r13array[c] = byte(c)
}
// Now pre-calculate the rot-13 values for A-Z and a-z
// These will override the value in the array
for c := 0; c &lt;= 26; c++ {
rot_13 := (c + 13) % 26
r.r13array[c + cap_A_offset] = byte(rot_13 + cap_A_offset)
r.r13array[c + low_a_offset] = byte(rot_13 + low_a_offset)
}
}
func (r rot13Reader) Read(b []byte) (int, error) {
numread, e := r.r.Read(b)
if e == nil {
for i := 0; i &lt; numread; i+= 1 {
c := r.r13array[b[i]]
// Just not worth doing something like &quot;if in != out&quot;
// before setting...I suspect that might even be slower.
b[i] = c
}
}
return numread, e	
}
func main() {
s := strings.NewReader(&quot;Lbh penpxrq gur pbqr!&quot;)
r := rot13Reader{s, [256]byte{}}
r.initialize_r13()
io.Copy(os.Stdout, &amp;r)
}

答案14

得分: -1

这是我解决问题的方法:

package main

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

type rot13Reader struct {
	r io.Reader
}

func rot13(r byte) byte {
	sb := rune(r)
	if sb >= 'a' && sb <= 'm' || sb >= 'A' && sb <= 'M' {
		sb = sb + 13
	} else if sb >= 'n' && sb <= 'z' || sb >= 'N' && sb <= 'Z' {
		sb = sb - 13
	}
	return byte(sb)

}

func (r13 *rot13Reader) Read(b []byte) (i int, e error) {
	n, err := r13.r.Read(b)
	for i := 0; i <= n; i++ {
		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)
}

希望对你有帮助!

英文:

Here's how I solved it:

package main
import (
&quot;io&quot;
&quot;os&quot;
&quot;strings&quot;
)
type rot13Reader struct {
r io.Reader
}
func rot13(r byte) byte {
sb := rune(r)
if sb &gt;= &#39;a&#39; &amp;&amp; sb &lt;= &#39;m&#39; || sb &gt;= &#39;A&#39; &amp;&amp; sb &lt;= &#39;M&#39; {
sb = sb + 13
}else if sb &gt;= &#39;n&#39; &amp;&amp; sb &lt;= &#39;z&#39; || sb &gt;= &#39;N&#39; &amp;&amp; sb &lt;= &#39;Z&#39; {
sb = sb - 13
}
return byte(sb)
}
func (r13 *rot13Reader) Read(b []byte) (i int, e error) {
n, err := r13.r.Read(b)
for i := 0; i &lt;= n; i++ {
b[i] = rot13(b[i])
}
return n, err
}
func main() {
s := strings.NewReader(&quot;Lbh penpxrq gur pbqr!&quot;)
r := rot13Reader{s}
io.Copy(os.Stdout, &amp;r)
}

答案15

得分: -1

以下是我翻译好的内容:

这是我的两分钱:

(注意,'Z' 的 ASCII 码是 90,'h' 是 114)

func (r rot13Reader) Read(p []byte) (n int, err error) {
	n, err = r.r.Read(p)
	if err == nil {
		for i := range p {
			if c := p[i] + 13; c > 'z' || (c > 'Z' && c < 'h') {
				p[i] = c - 26
			} else {
				p[i] = c
			}
		}
	}
	return n, err
}
英文:

Here are my two cents:

(Note that 'Z' ASCII code is 90 and 'h' is 114)

func (r rot13Reader) Read(p []byte) (n int, err error) {
n, err = r.r.Read(p)
if err == nil {
for i := range p {
if c := p[i] + 13; c &gt; &#39;z&#39; || (c &gt; &#39;Z&#39; &amp;&amp; c &lt; &#39;h&#39;) {
p[i] = c - 26
} else {
p[i] = c
}
}
}
return n, err
}

答案16

得分: -1

我的尝试:

package main

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

type rot13Reader struct {
	io.Reader
}

func (r rot13Reader) Read(p []byte) (n int, err error) {
	n, _ = r.Reader.Read(p)
	for i := 0; i < n; i++ {
		if p[i] != byte(' ') {
			if p[i] > byte('m') {
				p[i] = p[i] - 13
			} else {
				p[i] = p[i] + 13
			}
		}
	}
	err = io.EOF
	return
}

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

My Try:

package main
import (
&quot;io&quot;
&quot;os&quot;
&quot;strings&quot;
)
type rot13Reader struct {
io.Reader
}
func (r rot13Reader) Read(p []byte) (n int, err error) {
n, _ = r.Reader.Read(p)
for i := 0; i &lt; n; i++ {
if p[i] != byte(&#39; &#39;) {
if p[i] &gt; byte(&#39;m&#39;) {
p[i] = p[i] - 13
} else {
p[i] = p[i] + 13
}
}
}
err = io.EOF
return
}
func main() {
s := strings.NewReader(&quot;Lbh penpxrq gur pbqr!&quot;)
r := rot13Reader{s}
_, _ = io.Copy(os.Stdout, &amp;r)
}

答案17

得分: -1

我的解决方案是这样的:

func rot13(b byte) byte {
	in := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz")
	out := []byte("NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm")

	for i, v := range in {
		if v == b {
			return out[i]
		}
	}

	return b
}

type rot13Reader struct {
	r io.Reader
}

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
}
英文:

My solution was this:

func rot13(b byte) byte {
in := []byte(&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz&quot;)
out := []byte(&quot;NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm&quot;)
for i, v := range in {
if v == b {
return out[i]
}
}
return b
}
type rot13Reader struct {
r io.Reader
}
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
}

答案18

得分: -2

两年已经过去了,但我想分享一下我的代码,与之相比,它非常简单。

func (rot rot13Reader) Read(p []byte) (n int, err error) {
    n, err = rot.r.Read(p)  // 将字符串读入字节数组,n保存长度
    for i := 0; i < n; i++ {
        upper := p[i] >= 'A' && p[i] <= 'Z' // 新增
        lower := p[i] >= 'a' && p[i] <= 'z' // 新增
        if upper || lower { // 新增
            p[i] += 13 // 在这里进行简单的解码
            if (upper && p[i] > 'Z') || (lower && p[i] > 'z') { // 新增
                p[i] -= 26 // 如果超出范围,则循环到表格的另一侧
            }
        }
    }
    return
}

结果是什么?You cracked the code. 当然,实现所有ASCII字符会更好,但它仍然完成了大部分工作。


编辑:经过一年半的时间,由于其他人的错误编辑和对该错误的批评,我对这篇文章进行了编辑。编辑后的代码仍然保持了简单性,同时增加了一些额外的条件。此外,你可以很容易地将这段代码转换为rot13编码器。之前的输出是You-cracked-the-code.

英文:

two years has already passed since the question asked, but I want to share my code which was very simple compared to.

func (rot rot13Reader) Read(p []byte) (n int, err error) {
n, err = rot.r.Read(p)  // read the string into byte array, n holds the length
for i := 0; i &lt; n; i++ {
upper := p[i] &gt;=&#39;A&#39;||p[i]&lt;=&#39;Z&#39; //new
lower := p[i]&gt;=&#39;a&#39;||p[i]&lt;=&#39;z&#39;  //new
if (upper||lower){ //new
p[i] += 13   // we are simply decoding here
if (upper &amp;&amp; p[i] &gt; &#39;Z&#39;) || (lower &amp;&amp; p[i] &gt; &#39;z&#39;) { //new
p[i] -= 26 // and semi-circle the table if it goes beyond
}
}
}
return
}

the result? You cracked the code. Of course it would be better to implement all ascii scale, but it still does most of the job.


EDIT: After a year and a half, a bugged edit by someone else, and a critic about that bug led me to edit this post. The edit still keeps the simplicity of the code while providing few extra conditionals. Moreover, one can turn this code into a rot13 encoder easily. Previous output was You-cracked-the-code.

huangapple
  • 本文由 发表于 2015年7月28日 14:53:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/31669266.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定