Win a copy of Machine Learning for Business: Using Amazon SageMaker and JupyterE this week in the Jython/Python forum
or Object Design Style Guide in the Object-Oriented programming forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Bear Bibeault
  • Paul Clapham
  • Jeanne Boyarsky
  • Knute Snortum
Sheriffs:
  • Liutauras Vilda
  • Tim Cooke
  • Junilu Lacar
Saloon Keepers:
  • Ron McLeod
  • Stephan van Hulst
  • Tim Moores
  • Tim Holloway
  • Carey Brown
Bartenders:
  • Joe Ess
  • salvin francis
  • fred rosenberger

rot13Reader Exercise--Did I Do It Right?

 
Ranch Hand
Posts: 224
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Okay, I've been sailing along through "A Tour of Go" on my local machine. Some of the lessons have been pretty easy; some of them have been hard to understand; in the latter case, I've usually been able to figure them out if I tried hard enough. But right now I'm looking at the page with URL "127.0.0.1:3999/methods/23", with header "Exercise: rot13Reader", with contents:


A common pattern is an io.Reader that wraps another io.Reader, modifying the stream in some way.

For example, the gzip.NewReader function takes an io.Reader (a stream of compressed data) and returns a *gzip.Reader that also implements io.Reader (a stream of the decompressed data).

Implement a rot13Reader that implements io.Reader and reads from an io.Reader, modifying the stream by applying the rot13 substitution cipher to all alphabetical characters.

The rot13Reader type is provided for you. Make it an io.Reader by implementing its Read method.


and with example code (labeled as "exercise-rot-reader.go"):

So anyhow, I tried to complete the exercise by adding code to the example code resulting in:

When I click on <Run>, it runs, but it prints:

With that pair of statements repeated at least thirteen times across the screen. It might go more than thirteen times; I say thirteen times because when I spread my browser window over all three of my monitors, twelve instances of this pair and the beginning of a thirteenth is all I can see. Anyhow, does anyone know if this is what I'm supposed to see, having completed this exercise? And if not, do you know what I'm doing wrong with this exercise?
 
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Don't put long lines in code tags. It screws up the page formatting. Use the quote tags for text like that instead. I will change it for you this time.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Once again, familiarity with the documentation would help you. Read through what this says https://golang.org/pkg/io/#Reader.

It's better to follow the definition of the interface exactly, including the names used in the documentation. So instead of bffr, which is a horribly cryptic name (why are so many programmers averse to using vowels in the names they choose?), just use the equally cryptic but at least consistent name, p, instead.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You are supposed to see only as many characters as there were in the input. You're ignoring the return values of the Read function; you shouldn't do that. You need them to properly set up the for-loop. The one you set up is not right and it's the reason your output has much more in it than what it should have.

What I'm referring to is this:

The biggest problem with this line is that you throw away the int and error result. You need these. You are also passing the same array of bytes that was passed in to your Read function. That's definitely wrong. This means you don't have a clear idea of what the role of r io.Reader is in this whole process. EDIT: I take that back because it was based on an implementation I wrote that used two separate arrays and I see now that using the same array for both the plaintext and ciphertext can also work. Basically, you can apply rot13 in place.

You should take note of a few style issues in your code. You don't need the semicolon at the end of the line. Also, your formatting is not standard. I use Atom on a Mac and it would get rid of that space after the open parenthesis to conform with standard Go formatting conventions. And as I mentioned, the name bffr is cryptic and inconsistent with the Reader interface documentation, which uses p instead.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Also, rot13 would always add. To make the value wrap, you use the % operator. In my implementation, I defined a separate function to return the rot13 value of a single byte. That function is what I called from my Read function.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's a hint: in cryptography, the unencoded text is often referred to as the "plaintext" and the coded text is called the "ciphertext".

In your program, what represents the plaintext and what represents the ciphertext?

EDIT:

I originally wrote this thinking that it would lead you to create two separate arrays, one for the plaintext and the other for the ciphertext.  However, since you can solve the problem by applying the cipher in place as you show in your code, that's no longer point. It shifts a little bit now.

You still have to be clear on what each Reader is doing. You have two Reader implementations involved: your rot13Reader and the io.Reader that you're calling. Your rot13Reader is what is getting called by the io.Copy() function, which will have certain expectations about what it's going to get back from your Read() function. Those expectations are not being fulfilled by your current implementation. That's why you're getting the output you're seeing. Again, go back and carefully read the documentation for both the Reader interface and the io.Copy function.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
In this exercise, it's also important to understand how line 29 works.

Read https://golang.org/pkg/io/#Copy carefully so you know what to expect in your Read function and you can make it live up to what io.Copy expects from it. The way you've written it, your Read implementation is doing some surprising things, things that io.Copy doesn't expect, so naturally it's also giving some surprising results.
 
Kevin Simonson
Ranch Hand
Posts: 224
2
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Junilu Lacar wrote:In this exercise, it's also important to understand how line 29 works.

Read https://golang.org/pkg/io/#Copy carefully so you know what to expect in your Read function and you can make it live up to what io.Copy expects from it. The way you've written it, your Read implementation is doing some surprising things, things that io.Copy doesn't expect, so naturally it's also giving some surprising results.


Junilu, thanks for guiding me through this! My final code is:

And now it runs just fine. I know you said to use p instead of bffr, but I have a huge aversion to using one-letter variables, so instead I just spelled buffer out completely. Can you tell me why prevailing style frowns on writing the call to rr.read() with a space before its parameter?
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Kevin Simonson wrote:Can you tell me why prevailing style frowns on writing the call to rr.read() with a space before its parameter?


It boils down to style, really. Perhaps there's a bit of OCD involved but a space where you put it is asymmetrical because there's no space on the other end. I'm still adapting myself to Go style as well but it seems to me that brevity is a prevailing theme. I, too, have an aversion to single-letter variable names but I see no difference between i and ix and I find the latter just creates more noisy code. I guess I'd be OK with buffer over p if I was really pushed to be more expressive.
 
Junilu Lacar
Sheriff
Posts: 14759
245
Mac Android IntelliJ IDE Eclipse IDE Spring Debian Java Ubuntu Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Here's the latest refactoring of my implementation:

I know it's almost twice as long as what you wrote but I just like to make each method/function as simple as possible and I also wanted to avoid the duplication around the rot13 formula for uppercase vs. lowercase letters.
 
You didn't tell me he was so big. Unlike this tiny ad:
Java file APIs (DOC, XLS, PDF, and many more)
https://products.aspose.com/total/java
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!