Friday, March 30, 2012

Last day of my Apprenticeship

Today is the last day of my apprenticeship at 8th Light. Looking back at the last four months, I'm amazed by how much I've grown. The process was challenging, but very much worth it. Last fall, I promised myself that I would dedicate a few months of my life to learning about agile software development, and I just completed that goal. Check.

Having the opportunity to work with everyone at 8th Light was such a gift; people here are incredibly generous with their time and knowledge. There are some smart folks who spend their days in this office, and just having the ability to pick their brains on a daily basis has helped me to improve tremendously. I would recommend this apprenticeship to any and all developers who aspire to be better at what they do.

Moving forward, I'm excited to use what I've learned at 8th Light to build cool stuff. I've been hanging out with people who are involved in Open Gov Chicago, and I recently pulled together a Google Group for Urban Transportation Geeks—a collection of people who want to use open data sets and other tech resources to address transportation issues in our fine city.

Though my apprenticeship has officially ended, the learning process is far from over.

Monday, March 19, 2012

Refresh after SXSW

I spent the last week in Austin, Texas for SXSW, where I was surrounded by a wonderful concentration of folks who are excited about using technology to push society forward. Now back in Chicago, I'm slowly getting back into the swing of things and learning some new technologies as I go.

I recently completed my first Linux install on my Asus EEE netbook that was previously running Windows Starter 7 (blech). I've been wanting to use Ubuntu on this machine for awhile, but the limitations of my super sweet vintage iBook G4 finally prompted me to take action and make it happen. Now working on a Linux machine and without access to Textmate, I decided that this would be a good opportunity to learn Vim. Learning Vim has slowed my Artisan story progress, but it's worth it.

I don't have a whole lot to report on my progress, but I will say that it was very cool to go to SXSW and feel like I can have better conversations with other Ruby developers. Four months ago, I would have felt lost in conversation. I'm looking forward to seeing how my understanding progresses another four months down the road.

Friday, March 2, 2012

Juggling Notation Kata

I performed my first kata for 8th Light University today. It's a method that determines whether or not a pattern is composed entirely of repeating sub-patterns.

That is:
repeat?([4,4,1,4,4,1]) # => true
repeat?([3,3,3]) # => true
repeat?([4,4,1]) # => false


It was good to practice a kata over and over again until it felt like second nature. On the other hand, performing it in front of 60 people was a lot more difficult than I thought it would be. Under pressure, I somehow lost my ability to see detail, and I stumbled...and stumbled some more. Then I decided to erase my previous step and start over. I regained my composure and finished the kata.

Thinking, coding, narrating, and performing at the same time was quite challenging, but it's good to be challenged. If things are always easy and error-free, it's a good sign that you're stagnating in your progress.

Here's the code for my repeat Kata:

def repeat?(pattern)
  chunks(pattern).each do |chunk|
    if divides_evenly?(pattern, chunk)
      slices = []
      pattern.each_slice(chunk) {|sub| slices << sub}
      return true if slices.uniq.length == 1
    end
  end
  return false
end

def chunks(pattern)
  (1..pattern.length/2)
end

def divides_evenly?(pattern, chunk)
  pattern.length % chunk == 0
end

Tuesday, February 21, 2012

Siteswap in Sinatra

I started the day by working on some CSS animations that would use JavaScript to set class values and create an animated juggling pattern in the browser. But after I set up Jasmine and started working on the JavaScript portion of the project, I realized that it would make more sense for me to develop the Sinatra app first and focus on the JS once I have a stable application.

In other words, Patrick and Myles warned me against the dangers of creating stuff I don't need, and I listened.

Instead, I spent a good chunk of my day transforming my command line app into a Sinatra app. This required remembering how to use Sinatra, which was a lot easier today than it was two months ago. Most of the time I feel frustrated by not knowing or understanding as much as I'd like. But sometimes my progress hits me over the head and I actually feel like I've accomplished a lot in my time as an apprentice. Today is one of those days.

I still have to do some work to refactor my code and separate my application logic from the app display and the command line runner. But that's the small stuff. For now, I'm choosing to focus on the fact that it's working and it does what it's supposed to do.

Monday, February 20, 2012

Refactoring Siteswap

One of the coolest things about my apprenticeship at 8th Light is that I have the opportunity to pick lots of brains and learn how different craftsmen approach problems. Last Friday, I explained my siteswap problem to Li-Hsuan and we worked on the problem of efficiently removing arrays with repeating patterns. For example...

  • 1234512345 shouldn't exist. 12345 is fine.
  • 123123123 should just be 123
  • 121212 should be 12
  • 333 should be 3
You get the idea. He pointed out that you could get away with fewer calculations if you start with an array that's cut in half and then check the two halves, rather than starting with the smaller divisor and working your way up. For example, 123123123123 could be checked by a sub-string length of [1], then checked by [12], then checked by [123] (which would then return true because it's a repeating pattern)...or it could be checked once by [123123][123123]. Checking the larger divisor first will usually be more efficient.

Then I asked Colin to help me figure out why it takes so long to calculate longer sequences. I initially thought that it had something to do with my correct_timing method, but we soon discovered that it was actually Ruby's repeated_permutation function that was taking so much time to run. We talked about the potential of making a lazy method to return a smaller number of values, but I'm not sure if it's possible in this scenario. If I decide to turn this into a web app, I might need to pre-generate the values and then have the app run checks against an already-established list of possible throw sequences for different throw heights, number of juggling props, and number of throws in a sequence.

In the meantime, I implemented inclusion and exclusion functionality so that users have greater control over what types of values are returned.

And yes, I'm still pushing changes to GitHub.

Wednesday, February 15, 2012

Coding Siteswap

Jugglers have a notation called siteswap to explain different sequences of throws according to throw height. Thinking through the possible patterns for a given number of objects is an interesting math problem—a problem that I decided to attack in Ruby.

To determine the different throw patterns, I used Ruby's repeated_permutation method to find all of the possible throw sequences for throw heights 1-6. Then I added some filters:

def is_valid?  
 correct_number? && # number of objects thrown
 good_first_throw && # first throw must be high enough
 correct_timing == true && # you can only catch one thing at a time
 does_not_repeat # don't return 313131 when 31 will suffice
end


At the moment, I'm looking into this nifty JavaScript siteswap animator and seeing what it will take to make my Ruby code generate some sweet animations. I'm thinking that jQuery + an HTML5 canvas element would be pretty cool.

Here's the siteswap repo on GitHub.

Tuesday, February 14, 2012

Readings and Musings

Lately I've been reading a lot about different methods and theories for effective software development. I started with eXtreme Programming and I'm now in the middle of Software Craftsmanship by Pete McBreen. McBreen is unabashedly opinionated about the subject; his frank writing style makes me chuckle, but his thoughts are on point. There are a ton of great quotes and ideas from the book, but here's one of my favorites:

"After all, things rarely change just because of an idea; instead, they change because we act on the idea and make decisions based on it." -- Pete McBreen, Software Craftsmanship

I appreciate his fervent belief that craftsmen should build their reputation on beautiful work, and never settle for a mediocre delivery.

On other notes, I've been cranking away on my Rails application, looking into adding some JavaScript to the mix, and beginning to work on a juggling notation application. More on that later.

Thursday, January 19, 2012

Learning Rails

This week, I've dedicated a good chunk of time to stumbling my way through Rails. I expect to be confused for at least a few more days, but I'm thankful for the abundance of great tutorials and training materials out there for learning the basics of building Rails apps. I'm also glad that I know something about Ruby, Javascript, HTML, and CSS before jumping into Rails—it makes the learning process much easier.

I was surprised by how easy it was to set up a database and create a basic blog using Rails scaffolding. I was also surprised by how much information comes prepackaged in Rails -- jQuery, default stylesheets, etc. I spent some time just reading through the individual files and trying to figure out how all of the pieces work together. While it's nice that it only takes a couple of minutes to create a blog in Rails, I can't say that I fully understand the process, or have the ability to make meaningful modifications (yet).

I'm beginning to learn Rails by working on a Task Queue application concept that I thought of a couple of months ago. Right now, it's just an exercise, but if things go well then it could evolve into a useful application.

As a total beginner, so far this is my favorite Rails resource that I've found.

Monday, January 16, 2012

Divisible by 1 - 20

I learned quite a bit by finding the solution to this Project Euler problem:

2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder. What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?

At first, I attacked the problem with the goal of writing an algorithm that could solve it. I wrote some code that went through a giant array of numbers and checked to see if each one was evenly divisible by each of the numbers 1 - 20. This taught me a lesson in writing fast applications, since my process was using brute force rather than intelligent processes to solve the problem. I happen to be working on a beautiful, vintage 2004 iBook that runs at least some Ruby applications seven times slower than Doug's machine. This means that my brute force method wasn't going to cut it.

I re-wrote my code to eliminate items from the giant array if they weren't evenly divisible by just one of the numbers from 1 - 20, thus saving my computer the trouble of figuring out the remainder of 3, 4, 5, 6... if 31 isn't divisible by 2, anyway. This step alone brought down the speed of figuring out the smallest number divisible by numbers 1 - 10 from 19 seconds to 3.2 seconds. Wow.

Still, this wasn't good enough. The calculation speed was growing exponentially with each additional divisor, and I'm a very impatient person who doesn't like to wait.

I decided that I could also reduce the number of divisors that it was checking. I wrote some code to eliminate unnecessary divisors from a divisor array. Why check to see if it's divisible by 2, 4, or 8 when you already know that it's divisible by 16? Adding in this functionality reduced the time of finding the smallest number divisible by numbers 1 - 10 down from 3.2 seconds to .8 seconds. Progress.

Still, my code was checking too many numbers. Since the final number must be divisible by 20, why not build an array that only contains multiples of 20? Using the step method, I cut down the time to find the smallest number divisible by 1 - 15 from 21 seconds down to 1.98 seconds. Even better.

During lunch, I decided to just let the program run and find the answer for the smallest number divisible by numbers 1 - 20. It took seven minutes. Who knows how long it would have taken to find the answer with my original algorithm. I didn't have the time or patience to find out.

Then, Wai Lee came up to me and said, "Hey, I think I know a way to solve the problem without any code."

This morning, I tested Wai Lee's method with a pen and paper by listing out the multiples of each number 1 - 20, eliminating duplicates, and then multiplying the list of numbers: 5*7*9*11*13*16*17*19.

The result? I was able to come up with the same solution in about three minutes—that's 57% faster than my iBook could solve the problem with my "vastly improved" Ruby algorithm. Go figure.

This whole process taught me that there's a big difference between solving the problem and developing an elegant solution. I'm working on the latter.

If you're curious about what I did, check my spec on Github.

Tuesday, January 10, 2012

Unlocking the Grid

Today I spent more time solving Project Euler problems. I cranked through a number of problems, leaving a couple of them solvable but unsolved. It takes forever to run larger calculations on my iBook G4, especially if you're writing double for-loops to do millions of calculations. Maybe this means that I should use a different machine, but I think it's more likely that I need to think of a clever way to rewrite my code to avoid duplicate calculations.

For example:

# The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
# Find the sum of all the primes below two million.

def prime_array
  numbers = (2..7).to_a
  divisor = 2
  while divisor<10
    numbers.each do |x|
      numbers.delete(x) if x%divisor == 0 && x != divisor
    end
    divisor += 1
  end
  return numbers
end

def sum_of_primes
  sum = 0
  prime_array.each do |x|
    sum += x
  end
  return sum
end
 
puts sum_of_primes

# This takes forever to calculate


I put this problem aside for awhile and kept cranking through the problem set until I hit big one: The Grid Problem.

This is a fun one. I've run into a few stumbling blocks, but I'm hoping to finish it tomorrow.

Friday, January 6, 2012

Project Euler

I'm ridiculously excited to have discovered Project Euler, a collection a math problems that are perfectly suited for programmers. I stumbled across the site in search of a new kata, and since then, I've been a happy camper.

Not only did the site help me to take a step back from my confusion and tackle some fresh problems, but it is also giving me a ton of exercises that I can use to learn how to write acceptance tests. Just when I was about ready to give up on RSpec, Project Euler came to the rescue. The exercises are also a ton of fun.

You can check out my problems and answers on GitHub.

Tuesday, January 3, 2012

2011 who?

I had a great week. I stayed warm for the holidays, I played Settlers with friends, I drank hot cocoa, I worked on my grad school applications, and I jumped in the lake on New Year's Day to celebrate the arrival of 2012 with a wee bit of hypothermia.

But I didn't work on any Ruby projects. After a week off, I'm now scratching my head and trying to figure out what I thought I knew. Back to the basics.

I'm still reading through the RSpec book, and I'm now into the Cucumber section. I spent some time today looking back on the code that I wrote in 2011 and trying to write acceptance tests for it. I quickly realized that I need a basic Ruby refresher, so I spent some time re-writing my code and looking over documentation for the parts that still confuse me. With Ruby, everyday I'm moving two steps forward and one step back.

I've also identified a goal. In the next two months, I would like to publish at least one Ruby file to GitHub that helps others in some small way. I'd like to write a piece of code that solves a simple problem that Ruby developers face.

I'm open to suggestions.