Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement Go exercises #3

Closed
50 of 54 tasks
kytrinyx opened this issue Feb 28, 2014 · 36 comments
Closed
50 of 54 tasks

Implement Go exercises #3

kytrinyx opened this issue Feb 28, 2014 · 36 comments

Comments

@kytrinyx
Copy link
Member

Copied from exercism/exercism#237


To bring the Go path up to the same standard as the Ruby Path the following exercises need to be converted:

  • bob
  • word-count
  • anagram
  • beer-song
  • nucleotide-count
  • rna-transcription
  • point-mutations superseded by hamming
  • phone-number
  • hamming
  • grade-school
  • robot-name
  • leap
  • etl
  • meetup
  • space-age Just multiplying constants. No metaprogramming or anything (like in Ruby).
  • grains
  • gigasecond Not worth it in Go?
  • triangle
  • scrabble-score
  • roman-numerals
  • binary
  • prime-factors
  • raindrops
  • allergies
  • strain
  • atbash-cipher
  • accumulate Not a good problem in Go
  • crypto-square
  • trinary
  • sieve
  • simple-cipher
  • octal
  • luhn
  • pig-latin
  • pythagorean-triplet
  • series
  • difference-of-squares
  • secret-handshake
  • linked-list go stlib has a doubly linked list
  • wordy
  • hexadecimal
  • largest-series-product
  • kindergarden-garden
  • binary-search-tree
  • matrix
  • robot (robot-movement has no example, robot-pivots has no example)
  • nth-prime
  • palindrome-products
  • pascals-triangle
  • say
  • sum-of-multiples
  • queen-attack
  • saddle-points
  • ocr-numbers
@kytrinyx kytrinyx mentioned this issue Feb 28, 2014
54 tasks
@nathany
Copy link
Contributor

nathany commented Mar 15, 2014

I'd like to help port some of the Ruby tests/examples to Go.

@kytrinyx
Copy link
Member Author

That would be awesome, thank you! I'm guessing from twitter that you know a lot more Go than I do, and all help that will make the Go track better is very, very welcome!

@nathany
Copy link
Contributor

nathany commented Mar 16, 2014

@kytrinyx Oh, I don't know about that. You have been working on the CLI for a while, and Go continues to be an aside to my Rails day job. I am trying to contribute to the Go standard library, because those code reviews teach me a lot, but I seem to pick really hard problems. 😵

I noticed an x-common repo with READMEs that I presumably would copy across? Is there a particular order the exercises should run in (always insert at the end, match the order of Ruby)? Anything else I should know before picking one to add?

@kytrinyx
Copy link
Member Author

I've tried to document the current structure here: https://github.com/exercism/x-api/blob/master/CONTRIBUTING.md -- would you give that a read and then ask more questions if you have them?

You should not need to copy any READMEs, and there's no particular order. I try to adjust the order to have some sort of progression, but there's not really enough data at the moment, so I just kind of guess.

@nathany
Copy link
Contributor

nathany commented Apr 22, 2014

The gigasecond one is a bit odd and underdocumented https://github.com/exercism/x-common/blob/master/gigasecond.md

It looks like it's just an AddGigasecond function that operates on dates. Alternatively the tests could expect there to be a Gigasecond type with an Add() method.

@nathany
Copy link
Contributor

nathany commented Apr 22, 2014

(fyi, I can't check off the ones I've done...)

@kytrinyx
Copy link
Member Author

I've checked them off.

It looks like it's just an AddGigasecond function that operates on dates.

Yeah, that's true.

Alternatively the tests could expect there to be a Gigasecond type with an Add() method.

What would you be adding to the gigasecond in this case?

@nathany
Copy link
Contributor

nathany commented Apr 22, 2014

Actually, I'm not sure if Gigasecond makes a good exercise in Go. I'd probably implement the problem in terms of the standard library instead writing a function/method for it.

See: http://play.golang.org/p/XYNX78UFU5

@kytrinyx
Copy link
Member Author

Yeah, let's skip it. Thanks for playing around with that!

@bmatsuo
Copy link
Contributor

bmatsuo commented May 7, 2014

Thanks for putting in the effort on this! I think this project has some really good potential.

But I'd like to raise some concerns I have with copying these exercises over from a common repository. I don't think it's the best approach for learning Go or for getting people excited about Go. It's because the exercises are not designed to be implemented in Go.

My recommendation is that exercises either fork those found in the Go tour or follow the same general flow. There are not very many example there. So they could be supplemented with additional exercises. But the stuff covered there is far, far more valuable when learning to write Go.

You can stop reading. But I'll list some problems with the current exercises.

As a disclaimer I haven't grokked all the exercises (existing or yet to be translated). I've just been going through them in the suggested order to simulate the journey of a baby gopher.

The tests are promoting bad practices and anti-patterns. Its not the test structure (table-driven is good). But often the required function signature is bad. They should strictly conform to this document. Go is very prescriptive and that is the standard as far as style is concerned. Also, things like "accumulate" should be removed. There are lots of discussions about functions like that on the mailing list and the outcome is always the same. In short, it's not the right abstraction in Go.

The examples themselves do not enforce the parts of Go that need to be internalized by programmers. Go is very simple. And the exercises are very simple. The result is very boring. Compared to other languages there are very few distinct ways to implement these basic algorithms in Go. Which gives people much less to talk about and learn in the code review process.

Finally, the exercises do not realistically allow for the programmer to make use of interfaces or channels/goroutines. This is the biggest travesty of all. Go is made for writing highly concurrent software (like servers). It's the languages biggest strength and likely the reason the programmer is learning Go in the first place. You need to give the people what they want and early. Interfaces are super important in Go and people need to learn why they are good and when to use them. It's very important because the concept is not present is most languages and if it is, it may not be implemented the same way.

Please do not take offense to this criticism. I really appreciate the work you've done. But as I said I really like the idea behind this project and want to see it succeed. And in its current state it cannot be recommended a good way to learn Go. That makes me sad enough to rip it apart. 😢

I'll open some issues for examples I have specific problems with.

@kytrinyx
Copy link
Member Author

kytrinyx commented May 7, 2014

Thank you so much for your feedback. I wanted Go in here so much that I was willing to do it badly in the hopes that someone who knows it better would come along and tell me where I've gone wrong.

The examples themselves do not enforce the parts of Go that need to be internalized by programmers. Go is very simple. And the exercises are very simple. The result is very boring.

Hah. Yeah, I totally agree about simple and boring. It's definitely not a good resource to learn Go at the moment, not only because of the simplicity of the exercises, but also because there really isn't anyone around to give good feedback. We have a lot of "the n00bs leading the n00bs" going on, which in general seems to be an anti-pattern when learning.

The only exercise that is here from the tour is the word-count exercise. So far I feel like leap is a reasonable warm-up exercise, but might be more interesting if we make Year a type. word-count seems to work reasonably well as a warm-up exercise as well.

I would absolutely love to see the exercises reworked (and irrelevant exercises removed, and better exercises added). If you make suggestions, I'll do my best to implement them.

Because I don't really know Go well enough at this point, it's very hard to come up with exercises :/

@bmatsuo
Copy link
Contributor

bmatsuo commented May 7, 2014

I'll let you know if I come up with some good exercises. I can pitch in some effort implementing in my free time as well.

In general I would like to see things like "write a web server that does blah". Or "write something that reads values from channel and aggregates somehow". Or "write a function that does some stateful computation and make sure it can be called from multiple concurrent goroutines".

@kytrinyx
Copy link
Member Author

kytrinyx commented May 7, 2014

All of these suggestions sound stellar.

It might be nice to have several web server thingies to explore some of the common cases (serving static files, JSON api, chat server).

If I come up with anything I'll make a first pass at them and then ping you for feedback.

@bmatsuo
Copy link
Contributor

bmatsuo commented May 7, 2014

Yeah. Throwing some JSON in there would be very nice. Good practical experience.

Definitely ping me whenever you need feedback. :)

@bmatsuo
Copy link
Contributor

bmatsuo commented May 8, 2014

How about an exercise implementing func MultiWriter(io.Writer) io.Writer, a threadsafe writer. That is pretty straightforward and could be a fairly early exercise.

edit: maybe exercise ideas should be tickets..

@kytrinyx
Copy link
Member Author

kytrinyx commented May 8, 2014

edit: maybe exercise ideas should be tickets..

Yeah, good idea!

(I like the exercise idea, too)

@nathany
Copy link
Contributor

nathany commented May 9, 2014

One problem I've found when porting examples like grade-school is that it's hard to introduce a user-defined type into the code. It doesn't make much sense for the test to define a new type.

We don't have language-specific instructions or a starter .go script that could define a few things like the function signature and types expected by the test. Both of those may complicate the tools a fair bit. So far just converting to the underlying types in tests has worked okay.

@bmatsuo's comments bring up the question of the purpose of exercism. I've never thought of it as a tool intended to learn Go the way the Go Tour is.

That said, I've definitely noticed the function signature of tests limiting the possible solutions (such as whether or not to handle errors). In the case of grade-school I built it up as returning a map until I got to the requirement to return a sorted roster. Since maps in Go don't have a guaranteed order, a different return type is needed. But once the final tests are ready, people will need to start with that final type and deal with more requirements at once. Maybe that's not a bad thing, I don't know yet.

Looking forward to new exercises from @bmatsuo and improvements to the existing ones.

@bmatsuo
Copy link
Contributor

bmatsuo commented May 9, 2014

@nathany isn't this an example of what you are talking about? The Histogram type is defined in histogram.go, and that is copied over when the exercise is fetched.

@nathany
Copy link
Contributor

nathany commented May 9, 2014

@bmatsuo Oh, interesting. I hadn't ran into that one yet. Thanks!

@kytrinyx
Copy link
Member Author

kytrinyx commented May 9, 2014

I added the functionality to allow support files in the problems so that we could define types or, in the case of Scala, have a completely different directory structure. This opens up a number of possibilities.

@nathany
Copy link
Contributor

nathany commented May 9, 2014

@kytrinyx very nice. How do you deal with fetching an exercise a second time and overwriting things?

Would the word count test.go file be overwritten but not histogram.go?

@kytrinyx
Copy link
Member Author

kytrinyx commented May 9, 2014

Nothing gets overwritten. If someone wants to get the most up to date test suite they can explicitly delete things. This isn't actually documented anywhere sigh.

@nathany
Copy link
Contributor

nathany commented May 9, 2014

Ahh, documentation. The bane of every programmer? 😛

@kytrinyx
Copy link
Member Author

kytrinyx commented May 9, 2014

I'm working on a docs site, and hope to have it launched in the next couple of weeks. That might make it more tempting to actually document things.

@soniakeys
Copy link
Contributor

The next problem on the list, space-age, is one I'd nominate to omit. It's multiplying a number by constant. In my real-life astronomy code, I don't write functions or types or classes for anything like this. I define constants and that's all, they get no wrapping. Then I just use them, multiplying with a * operator whenever I need a number multiplied by one of the constants. I really find it obscuring to put constants behind functions that claim to be doing some sort of conversion. I just want to use my constants.

Gigasecond, already nominated for omission, I actually see more value in. It's kind of interesting to me that you can pass 1e9 in the seconds field to the date constructor. It might be kind of interesting if you've never worked with time objects, to see that you can do arithmetic with them. After that though, the whole exercise really is nothing more than just adding two values. I agree it's not that interesting overall.

Triangle, I just pushed to a branch. I kept the test cases of Ruby. I dropped the part about not a triangle being an error. The point is to identify one of four cases, equilateral, isosceles, scalene, or not a triangle. Not a triangle isn't an error until you try to do some computation that requires a non-degenerate triangle. The exercise is very simple, but there are several ways to approach it. It should be good for discussion just as it is.

It could be expanded though. The first thing I would add would be Inf and NaN test cases. 1, +Inf, +Inf is not an isosceles triangle, and 1, 2, NaN is not a scalene triangle. There are other simple kinds of triangles, acute, obtuse, right. Kinds aren't mutually exclusive, so it might be interesting to return something that represents the set all kinds that are true of a triangle.

@kytrinyx
Copy link
Member Author

kytrinyx commented Jun 4, 2014

I agree that we should omit the SpaceAge one. In Ruby it's useful as a way to explore metaprogramming.

Gigasecond I'm totally open to including. Perhaps it's a good first or second exercise?

Triangle—this isn't an exercise that I gave a lot of thought to (hm. That's true for most of them, and I really appreciate that you're providing thoughtful criticism about these as you're working through them!). I really like the idea of extending this, as the added requirements allow the code to go in more diverse directions.

@sjakobi
Copy link
Contributor

sjakobi commented Jun 4, 2014

If anyone's looking for existing implementations of exercises - I've made a webapp to make finding them easier:
http://please-implement.appspot.com.

Click on the "Go" column header to get a list of the exercises that haven't been implemented in Go sorted by number of existing implementations.

@kytrinyx
Copy link
Member Author

kytrinyx commented Jun 4, 2014

That's brilliant!

@soniakeys
Copy link
Contributor

Amazing. So much to implement! Oh, Zebra puzzle. You know, that and and a few other constraint problems are on Rosetta Code and I haven't done any of them yet (well, except for Sudoku, it was kind of close to my heart.) I haven't done them because I'd love to find a good general way of expressing constraints. Then you could write constraint solvers to that input format and solve whole classes of problems easily.

@soniakeys
Copy link
Contributor

❤️ the sort feature. I'll start going by that for picking the next exercise to implement.

@kytrinyx
Copy link
Member Author

kytrinyx commented Jun 4, 2014

I really liked Aja Hammerly's talk on using Prolog to solve constraint problems a couple years ago: https://www.youtube.com/watch?v=hEOVcLAPRG8

@soniakeys
Copy link
Contributor

I've been working on robot simulator. The ruby test program has multiple robots in a room. This really cries for concurrency, but it's a pretty big problem for an introduction to concurrency. What do people think of maybe something like a barber shop problem for an introduction?

(Can Travis handle sleep? It would be nice for test programs to be able to sequence things with sleeps and expect repeatable results from the example.)

Really wandering now...

"Little Book of Semaphores" has a big collection of concurrency problems. I have to say though I find most of the problems in this book unsatisfying. Many of them are posed as simulations of physical systems, yet the solutions given often gloss over physicality issues and end up being exercises in understanding that the exercise is to use some specific concurrency construct in a certain way. No doubt the exercises are helpful in learning the constructs, but it's not clear how well it all applies to real-world concurrency problems.

In contrast are problems like paasio or the web crawler exercise from A Tour of Go . I love these because they present simplified versions of problems that I imagine programmers must commonly solve in the real world. Hmm, embarrassingly parallel tasks are super common. Oh wait, we have parallel letter frequency. That's a pretty good introductory exercise. Mmm, I'll stop here. This all needs much more thought.

(Next day) Oh, there's bank-account. I hadn't noticed that one.

@soniakeys
Copy link
Contributor

@kytrinyx for saddle-points, would it work to put a comment in the go test program inviting solvers to copy their matrix.go into their saddle-points directory and just submit additional code as saddle-points.go? The only awkward point might be that nitpickers wouldn't have the solver's matrix code right in front of them when nitpicking the saddle-point code, but since the matrix api would be the same for everyone, it shouldn't be too obscure.

Or...is part of the exercise for solvers to recognize on their own that they might build on their matrix code?

@kytrinyx
Copy link
Member Author

I think it's fine to suggest that they can use their matrix code. With beginners it's useful to make them solve it twice if they don't recognize the similarity, but I don't feel strongly about it at all.

@soniakeys
Copy link
Contributor

We're getting close to closing this issue! The last exercise not crossed off one way or another is linked-list, and I'll suggest that this, and also simple linked-list, are not good excises for Go.

Go has a doubly linked list in the standard library. While it may have some good use cases, almost always when someone mentions it on a Go discussion list, it comes out that it is not appropriate for their problem. This exercise is reimplementing something which is almost always ill-advised in the first place.

In simple-linked-list, I'm struggling to identify the key concepts of the exercise and which of those might be relevant to Go. Go has pointers, it's very straight-forward to implement linked lists, but like doubly linked lists, even singly linked lists are also almost always ill-advised. Slices are almost always better. Go slices have a sort of persistence. If you append to a slice, the original remains unchanged, as viewed by anyone with a reference to the original. But the exercise does nothing to illustrate persistence. The exercise mentions stacks but doesn't illustrate them. Reversing and converting, well sure, we can do that, but it doesn't really seem to me that these operations illustrate any properties of linked lists. Finally the readme uses the term abstract data type. Well, I would like to show a good use of interfaces, Go's take on abstract types, but I think that direction would lead far away from the readme and the implementations in other languages.

@kytrinyx
Copy link
Member Author

These are all excellent points. I think we should ignore both of the linked list exercise. I've updated the config.json to reflect this, and (drumroll) I'm closing this issue!

Thanks so much for putting in so much effort in getting the exercises implemented, and improving them so that they are better for Go!

✨ ❤️ ✨

bobtfish added a commit to bobtfish/exercism-go that referenced this issue Oct 3, 2021
bobtfish added a commit to bobtfish/exercism-go that referenced this issue Oct 3, 2021
bobtfish added a commit to bobtfish/exercism-go that referenced this issue Oct 3, 2021
jmrunkle added a commit that referenced this issue Oct 5, 2021
* Remove mention of multiple return values this early

* Move variables and constants explanation to before functions.

This matches the order of the first task in the exercise.

* Try to solve unclear errors about return types, test errors etc.

Fixes #1763. Fixes point #4 in #1745

* Clarify that all entities can be accessed in packages if capitalised

Addresses point #2 from #1745

* Add note that we use camelCase in go.

Addresses point #3 of #1745

* Add myself as a contributor to the exercise

* Apply suggestions from code review

Co-authored-by: Jason Runkle <jmrunkle@gmail.com>

* Make the hints be bullet point list

Co-authored-by: Jason Runkle <jmrunkle@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants