Exercise: Rot13 Reader , can not get correct answer in A Tour of Go

630 views
Skip to first unread message

hao5ang

unread,
Dec 10, 2012, 11:57:01 AM12/10/12
to golan...@googlegroups.com
This exercise:
http://tour.golang.org/#61
My answer : 
func (b *rot13Reader) Read(p []byte) (int, error) {
n,err := b.r.Read(p)
n = n
err = err
//if err != nil{
// panic(err)
//}
for i, v := range p {
if v >= 'a' && v <= 'z'{
p[i] = (v-'a'+13)%26 + 'a'
}else if v >= 'A' && v <= 'Z'{
p[i] = (v-'A'+13)%26 + 'A'
}
}
return len(p), nil
}
My result is always : You cracked
When I release the if clause it can get the right answer with panic :You cracked the code!panic: EOF ...
When I install the code in my local win 64 machine , I can get the screen rolls infinitely with :You cracked the code! and Lbh penpxrq gur pbqr!
I can't understand . Can someone help me ?

Another try : When I change return from len(0),nil to n,nil , I get this answer : You cracked the code! [process took too long]

Peter

unread,
Dec 10, 2012, 12:23:26 PM12/10/12
to golan...@googlegroups.com
First of all, you need to return n, not len(p).

Secondly, you need to return the error you got from calling the inner Read() method, else you won't be able to signal the EOF.

As to why this happens, it's a bit complicated: The tour code copies from your reader to stdout, and does so in large (32kB) chunks. So your reader was reporting that it had read "len(p)" == 32000 bytes - when of course it hadn't done anything like that. Also since it always returned "nil" as its error, the copy function never knew it had finished and eventually ran out of time.

Finally, you can remove the "n=n" stuff, as you're now using n and err as your return values, so the compiler won't complain that they're unused.

Hope that helps.

hao5ang

unread,
Dec 10, 2012, 12:37:19 PM12/10/12
to golan...@googlegroups.com
That really helps.

I know what is correct . But I also want to know why I get the truncated result "You cracked " when I return the len(p) and nil . The len(p) should be 32768 . But the result length is not more than 20 .
Thanks.

Peter

unread,
Dec 10, 2012, 1:11:17 PM12/10/12
to golan...@googlegroups.com
I don't know why it was truncated. I wouldn't worry about it.

If you dive in to the source code for os.Stdout (not recommended at your stage :P), you will find a comment:

// If the syscall wrote some data but not all (short write)
// or it returned EINTR, then assume it stopped early for
// reasons that are uninteresting to the caller, and try again.

hao5ang

unread,
Dec 10, 2012, 9:04:34 PM12/10/12
to golan...@googlegroups.com
Thanks for your kind help .

hao5ang

unread,
Dec 10, 2012, 9:06:46 PM12/10/12
to golan...@googlegroups.com, itmi...@gmail.com
If I panic(p) I can get p == 32768 . So it's not an infinite loop .

On Tuesday, December 11, 2012 3:04:50 AM UTC+8, itmi...@gmail.com wrote:
Maybe because this for i, v := range p { translates to this for {, an infinite loop?

Dave Cheney

unread,
Dec 10, 2012, 9:10:35 PM12/10/12
to hao5ang, golan...@googlegroups.com
Please reread the contract for io.Reader. Read will read some number
of bytes of data into the buffer you supply and return the number of
bytes read *AND* possibly an error. You should do two things on every
round of Read()ing

1. reslice p to p[:n]
2. process any data returned in p *before* dealing with the error
condition. Not doing so could lead to missing data in the final read.
> --
>
>

hao5ang

unread,
Dec 11, 2012, 1:28:32 AM12/11/12
to golan...@googlegroups.com, hao5ang
Yes , we should use this correct method.

hao5ang

unread,
Dec 11, 2012, 1:32:55 AM12/11/12
to golan...@googlegroups.com, itmi...@gmail.com
Yes , it's like an infinite loop because the number 32768 is very big . Thanks.

On Tuesday, December 11, 2012 1:20:52 PM UTC+8, itmi...@gmail.com wrote:
On Tuesday, December 11, 2012 4:06:46 AM UTC+2, hao5ang wrote:
If I panic(p) I can get p == 32768 . So it's not an infinite loop .


It is. That's why you get [truncated], because the result to display is just too long. The "screen rolls infinitely" you've mention in your first post.

Here's a simple test: http://play.golang.org/p/daUBkeY0on

You'll want to run the test locally, it doesn't work on the online playground. You'll notice the values just keep piling up.


Reply all
Reply to author
Forward
0 new messages