我正在尝试解决Golang巡回练习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!”的第一个单词。破了。我该如何破解整个句子?
答案 0 :(得分:11)
修改强>
基本上你的解决方案很好并且有效,你输错了1个字符:
case x >= 110 && x >= 122:
将其更改为:
case x >= 110 && x <= 122:
您的输入和输出:
Lbh penpxrq gur pbqr!
You prnpxrq tur poqr!
每个词都有变化。问题不在于只有第一个字被读取和解码,问题在于你的解码算法。
在ROT13中如果移位超出字母范围,则必须从字母表的开头(或结尾处)开始。例如,转移'N'
将为'Z'
+ 1,因此它将成为'A'
,即第一个字母。看到这个简单的字符映射:
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
NOPQRSTUVWXYZABCDEFGHIJKLMnopqrstuvwxyzabcdefghijklm
所以你应该做的是在移动13之后,如果字母超出字母表,将其移动-26
(英文字母中的字母数),这会产生预期效果(在最后一个之后)你从第一个继续写的信。)
示例解决方案:
func rot13(x byte) byte {
capital := x >= 'A' && x <= 'Z'
if !capital && (x < 'a' || x > 'z') {
return x // Not a letter
}
x += 13
if capital && x > 'Z' || !capital && x > 'z' {
x -= 26
}
return x
}
及其输出:
You cracked the code!
在Go Playground上尝试。
答案 1 :(得分:3)
您也可以使用:
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]
}
答案 2 :(得分:2)
我更喜欢在rot13函数中直接操作整数
contoso.com
www.contoso.com
http://www.contoso.com
http://contoso.com
答案 3 :(得分: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)
}
答案 4 :(得分:1)
问题是您的功能无法正常工作。要验证这一点,只需尝试在"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 。代码取自here。
答案 5 :(得分:1)
我的代码也有效,它更简单!
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
}
答案 6 :(得分: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
}
}
答案 7 :(得分:1)
还有另一种方法:
func (rr *rot13Reader) Read(b []byte) (int, error) {
n, err := rr.r.Read(b)
if err != nil {
return 0, err
}
for i := 0; i < n; i++ {
if b[i] >= 'A' && b[i] <= 'z' {
b[i] += 13
if b[i] > 'z' {
b[i] -= 26
}
}
}
return n, nil
}
答案 8 :(得分:0)
作为@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 {
// byte isn'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 :(得分:0)
You-cracked-the-code.
结果? {{ range $.Site.Languages }}
<span href="#"> {{ .Lang }} - {{ .LanguageName }} </span>
{{ end }}
当然,实施所有ascii规模会更好,但它仍然可以完成大部分工作。
答案 10 :(得分:0)
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
}
答案 11 :(得分:0)
这是我解决的方法:
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)
}
答案 12 :(得分:0)
这是我的两分钱
(请注意,“ 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
}
答案 13 :(得分: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
}
答案 14 :(得分:-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)
}
答案 15 :(得分:-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
}