Go Challenge - 1

The world’s first monthly Go Challenge for developers (newbies included)


update.jpg

Feedback from the Evaluators

Difficult to give generalized comments, but here are some suggestions.

  1. Running go vet and golint should be a no-brainer. I found that a few entries failed this test.
  2. Use the defer statement to free up resources after use - for example, on file open.
  3. Do not over-engineer. Types are easy to define, but sometimes, all you need is a func.
  4. Comment your code well. What may seem obvious to you may not be so obvious to someone reading your code.

A more detailed feedback is available here.


Matt Aimonetti: Author of the first Go Challenge

Matt Aimonetti The first Go Challenge author is Matt Aimonetti, CTO and co-founder of Splice, a technology platform for music creators. Splice streamlines the fragmented process of creating and sharing music, freeing musicians to spend their time and energy on the creative process.

Long before Splice, Matt was a former sound engineer who tried his hand as an artist before transitioning to full time programming, working for companies such as Sony PlayStation and LivingSocial. Matt has been active in the Open Source community for many years, developing or contributing to many projects (Merb, Rails, MacRuby and many more). He also wrote a free book about Go and is a published tech author for O’Reilly. Matt is based in Santa Monica, California.

Matt has this to say about the challenge:

“Very often developers just need an excuse to learn a new language or develop their own skills. The Go challenge is a great opportunity to work on a low-pressure, isolated, fun challenge and hopefully learn a lot. Getting out of the day to day programmer routine is an awesome way to challenge your brain and become a better developer.”


The Go Challenge 1

This morning I took my daughter Giana to my secret lab to show her the various inventions I built over the years. That’s when I realized that the awesome drum machine prototype I designed in the 90s had disappeared!!! The only related things I could find were printouts of the patterns I had created on the device as well as backups saved on floppy disks. Here are the printed patterns:

pattern_1.splice
Saved with HW Version: 0.808-alpha
Tempo: 120
(0) kick     |x---|x---|x---|x---|
(1) snare    |----|x---|----|x---|
(2) clap     |----|x-x-|----|----|
(3) hh-open  |--x-|--x-|x-x-|--x-|
(4) hh-close |x---|x---|----|x--x|
(5) cowbell  |----|----|--x-|----|
pattern_2.splice
Saved with HW Version: 0.808-alpha
Tempo: 98.4
(0) kick    |x---|----|x---|----|
(1) snare   |----|x---|----|x---|
(3) hh-open |--x-|--x-|x-x-|--x-|
(5) cowbell |----|----|x---|----|
pattern_3.splice
Saved with HW Version: 0.808-alpha
Tempo: 118
(40) kick    |x---|----|x---|----|
(1) clap     |----|x---|----|x---|
(3) hh-open  |--x-|--x-|x-x-|--x-|
(5) low-tom  |----|---x|----|----|
(12) mid-tom |----|----|x---|----|
(9) hi-tom   |----|----|-x--|----|
pattern_4.splice
Saved with HW Version: 0.909
Tempo: 240
(0) SubKick	      |----|----|----|----|
(1) Kick	      |x---|----|x---|----|
(99) Maracas	  |x-x-|x-x-|x-x-|x-x-|
(255) Low Conga	  |----|x---|----|x---|
pattern_5.splice
Saved with HW Version: 0.708-alpha
Tempo: 999
(1) Kick	|x---|----|x---|----|
(2) HiHat	|x-x-|x-x-|x-x-|x-x-|

I need your help to reverse engineer the binary format used by my drum machine and write a decoder so I will be able to implement a new drum machine, using Go this time!

To get started

You will find attached a zip file containing the starting point for this challenge. Your goal is to implement the drum package and make it pass the provided tests.

Some information about my legacy drum machine

My drum machine loads an audio sample per track, allowing the programmer to schedule the playback of the sound. The scheduling of the playback is done using the concept of steps. A step is one of the parts of the measure that is being programmed (the programmed measure is known as a pattern). The measure (also called a bar) is divided in steps.

measure.png

My drum machine only supports 16 step measure patterns played in 4/4 time. The measure is comprised of 4 quarter notes, each quarter note is comprised of 4 sixteenth notes and each sixteenth note corresponds to a step. If all these music terms are confusing, don’t worry, just know that the drum machine uses grid of 16 parts to let you trigger a sound. We have one sound per track and each track can be programmed independently. Each part is called a step. The speed of the playback is based on the tempo (aka bpm).

Taking an example from the printouts above: (40) kick |x---|----|x---|----|

means that we have a track called “kick” (id 40) with the sound output being triggered on the first and ninth steps.

Goal

The goal of this challenge is to write a binary decoder that given a binary backup, outputs the same printouts as shown above. To do that you need to implement the DecodeFile(path string) (*Pattern, error) function inside the drum package. Note that *Pattern needs to be printable so it can be compared to the printouts. To help you, a test is provided. To run the test suite, use your terminal to navigate to the location of the unzip file and run go test -v. You should see an output similar to this:

go test -v
=== RUN TestDecodeFile
--- FAIL: TestDecodeFile (0.00s)
	decoder_test.go:69: decoded:
		"&{}"
	decoder_test.go:70: expected:
		"Saved with HW Version: 0.808-alpha\nTempo: 120\n(0) kick\t|x---|x---|x---|x---|\n(1) snare\t|----|x---|----|x---|\n(2) clap\t|----|x-x-|----|----|\n(3) hh-open\t|--x-|--x-|x-x-|--x-|\n(4) hh-close\t|x---|x---|----|x--x|\n(5) cowbell\t|----|----|--x-|----|\n"
	decoder_test.go:72: pattern_1.splice wasn't decoded as expect.
		Got:
		&{}
		Expected:
		Saved with HW Version: 0.808-alpha
		Tempo: 120
		(0) kick	|x---|x---|x---|x---|
		(1) snare	|----|x---|----|x---|
		(2) clap	|----|x-x-|----|----|
		(3) hh-open	|--x-|--x-|x-x-|--x-|
		(4) hh-close	|x---|x---|----|x--x|
		(5) cowbell	|----|----|--x-|----|
FAIL
exit status 1

Requirements

  • Only use Go standard library. No third-party libraries may be imported.
  • You are welcome to modify (improve) the included test suite or move the binaries, but the DecodeFile API must remain and the original test suite must still pass.

Hints

I don’t know where to start :(

Hex Viewer

The first step is to reverse engineer the binary file format. Look at the hex values to see if you can detect patterns. Binary data usually contains some sort of headers, then the encoded data. You should expect to find the data described in the printouts:

  • version
  • tempo
  • tracks with each track containing
    • id
    • name
    • 16 steps

Then you need to write a decoder that takes one of the provided binary files and extracts/prints the data.

Go further (optional, not evaluated for the challenge)

This advanced section is not for the faint of heart, in case you were about to complain about how easy this challenge was, or if you just want to push things further, here is some more!

How about editing the cowbell track to add more steps? Reading the binary format is one thing, being able to generate/modify the data is even more fun. Take a pattern of your choosing and add more cowbell! For instance convert pattern_2.splice from:

pattern_2.splice
Saved with HW Version: 0.808-alpha
Tempo: 98.4
(0) kick    |x---|----|x---|----|
(1) snare   |----|x---|----|x---|
(3) hh-open |--x-|--x-|x-x-|--x-|
(5) cowbell |----|----|x---|----|

to:

pattern_2-morebells.splice
Saved with HW Version: 0.808-alpha
Tempo: 98.4
(0) kick    |x---|----|x---|----|
(1) snare   |----|x---|----|x---|
(3) hh-open |--x-|--x-|x-x-|--x-|
(5) cowbell |x---|x-x-|x---|x-x-|

Still not enough? Why not implementing the playback of the patterns using something like portaudio?


Challenge Rules and how to enter the Go Challenge?

By participating in this challenge, you agree to be bound by the Challenge Rules below:

  • The Challenge is open to individuals.
  • After the challenge, all submissions will be made available online on GitHub under the BSD 3-Clause License.
  • Evaluators cannot enter the challenge except under the “Just for Fun” category.
  • Each entrant shall indemnify, defend, and hold JoshSoftware Pvt. Ltd. (who has sponsored the domain and is the organizer of these challenges) harmless from any third party claims arising from or related to that entrant’s participation in the Challenge. In no event shall JoshSoftware Pvt. Ltd. be liable to an entrant for acts or omissions arising out of or related to the Challenge or that entrant’s participation in the Challenge.
  • Odds of winning depend on the number and quality of entries received.
  • All taxes, including income taxes, are the sole responsibility of winners.
  • No prize substitution is permitted.
  • Create a zip of your Go source code and send the zip file to gochallenge [at] joshsoftware.com by the 13th of March 2015 (6 am IST). Use this link to find the equivalent time in your city/country. No new solutions will be accepted after that. In the email mention your full name, country of residence, and twitter id (if any). We shall be publishing on this blog, a list of participant names. If you don’t want you name to appear kindly mention the same in your email. We are accepting anonymous submissions and will evaluate them too but then these participants are not eligible for the prizes. We will give your zip file to the evaluation team. Note: Avoid sharing your code with anyone else; if your solution becomes available to the general public it might impact evaluation of your submission.

How will the challenge be evaluated?

Entries will be anonymized and evaluated by the challenge author and a team of evaluators.

  • Functioning code and a test suite that passes.
  • Code hygiene. Use gofmt, vet and lint. Review CodeReviewComments.
  • Readability. How easy is it for another programmer to grasp what your entry is doing?
  • Code structure. Do types and files have good names?
  • Reliability. Are errors properly handled?
  • Appropriate consideration given to memory and performance (nothing is unnecessarily expensive).

Questions?

If you have any questions about this challenge, please join the golang-challenge channel on slack which is a room for people who are going to participate in the Go Challenge.

Evaluators

Nathan Youngman has agreed to set the guidelines for evaluation. Dominik Honnef, Guillaume J. Charmes, Jiahua Chen, Niket Patel, Pravin Mishra and Sanat Gersappa have agreed to go through all the submitted solutions of a challenge. They will comment and rank these solutions.

Best Solution

The author of the Go Challenge will decide the best two solutions. The author shall have the sole authority and discretion to select the award recipients.

Notification

The winning entries will be announced here on this blog. The winners will be sent their prizes by email/postal mail.

Prizes

Two prizes will be awarded for the best solution as selected by the author.

Here are some great prizes provided by our sponsors for the event.

Winner 1:

Winner 2:

Anyone can a get 42% off on the price of the following eBooks from Manning Publications Co.:

Also, anyone can a get 25% off on the price (valid till 31st March 2015) of the following print and / or eBooks from Packt Publishing:

Winner Interviews

After a winner wins the monthly challenge, he/she would be interviewed by Sourcegraph and the interview will be published on their blog.

The Participants

You can check out the list of participants for this challenge i.e. for March 2015.

Challenge Solutions

All the solutions submitted by the participants are available here.

The Winners

winner.png

Matt Aimonetti has selected the winners of this challenge. They are:

Luke Champine Winner #1 Luke Champine never expected to wind up as a programmer; in college he first studied electrical engineering, and then computer engineering. But he got involved in his school’s open source community, which sparked his love of programming and introduced him to Go. He left school without graduating and moved to Boston to co-found Nebulous, a cryptocurrency startup.

Outside of programming, his interests include linguistics, Buddhism, and chess.

His solution to the challenge.


Jeremy Jay Winner # 2 Jeremy Jay has been a developer for almost 20 years now. He earned his PhD in Computer Science in 2013, and runs a freelance software development company specializing in mobile apps and complex data integration projects (which often go together!). He has developed applications for all 5 major Operating Systems (Linux, OSX, Windows, iOS, Android), some smaller/embedded ones, using the myriad languages he had picked up along his career. Go is by far his favorite, and has become his daily driver, even for things he used to write short python scripts for. Go’s brevity and expressiveness makes it extremely versatile for his daily work.

His solution to the challenge.


Matt also mentioned that Doug Cichon was a very close #2.

Sponsors

This challenge’s sponsors are: Anand D N, Apcera, CoreOS, Crowd Interactive, Cube Root Software, DigitalOcean, Docker, GopherCasts, Helpshift, InfluxDB, John Sonmez, JoshSoftware Pvt. Ltd., Manning Publications Co., NodePrime, O’Reilly, Packt Publishing, Qwinix Technologies, RainingClouds, SoStronk and Sourcegraph.

Credit

  • The Gopher character is based on the Go mascot designed by Renée French and copyrighted under the Creative Commons Attribution 3.0 license.
  • The Go Challenge is being organized by JoshSoftware Pvt. Ltd. with help from the Go community.
Written on March 1, 2015