Lots of lessons learned these past few days:

1) Sometimes a weekend full of chores, reading and naps is just what the doctor ordered.

I didn’t open up my computer until Sunday evening (a full 48 hours sans programming) and although I worried that I’d lose steam on what I was doing I’ve been completely recharged these past few days. I feel like I’ve been able to think more clearly than I have in weeks. My reading this weekend was finishing up XP Explained and working on Refactoring- but I’m not ashamed to admit that I probably napped 20 minutes for every 20 pages I read.

2) Recursion and Refactoring are FUN!

While on my minimax quest these past couple of weeks someone brought up the N-Queens problem, where you must place N number of queens on an N x N board without any of them being able to attack each other. I took a run at it last week for an hour or two and my solution ended up being very much like my first run at unbeatable tic-tac-toe. The logic was hard-coded and a massive if-else chain. Sunday night I started to sketch out another run at it with the idea of a constructing a “learner” that could track its steps and backtrack when necessary- which is a lot like what I need to do with minimax.

The hard-coded logic for the problem is relatively straightforward (the layout of the Queens typically follows the movement of a knight- in an “L” shape), but developing a “figurer” was a definitely a challenge. I started out with a pretty rigorous barrage of tests to find out if a board had any attacks possible, and my thinking was that I could use those methods to place pieces. But the methods ended up being iterative and rigid and as I delved deeper I realized that I could write more organic methods. As my loop gained more whiles, ifs and some recursion I had to throw testing to the wind. When something is “untestable” it’s a good indication that it’s too complex, but I’m just not that good yet to be able to test-drive a brain teaser like this one. Instead I let the method grow into a 30 line monster with many lines pushing the 80 character limit, way too much duplication and a nasty mess of puts statements to help me figure out what did and didn’t work.

After spending a good chunk of time with it on Monday I had it solved up to 15 queens with some odd inconsistencies between 16 and 20 queens. Depending on what lines I commented out I could solve for 16, 18 and 19 but not 17 and 20 or vice versa. I went to bed last night determined to find out what was going wrong. When I got up early this morning I made one simple reorder of my flow control and was greeted with a sea of green passing tests. For a solid 10 minutes I debated waking up Rosa so that I could get a well-deserved high five, but it’s a really good thing I didn’t because once I was fully awake I realized that not only hadn’t I fixed it, but I’d missed a line in my latest batch of tests- which is the only reason they all passed. Ugh. But I kept at the refactoring/deleting/drying and a little while later had the massive A-HA moment when not only was I able to get it work but I took the monster down to about 10 lines (gist).

 def coordinates_for_next_move
   while attackable(@row,@column)
     @column += 1 if @column < @size
     while @column >= @size
       @row = @positions.last[0]
       @column = @positions.last[1] + 1
       @positions.delete_at(@positions.count - 1)
     end
   end
   place_next_queen
 end

*place_next_queen shovels the row and column to the positions array and then calls coordinates_for_next_move

It’s definitely still not perfect (it only solves for up to 20 queens before I get a “stack level too deep” error) and there’s plenty of code to clean up (like that nested while statement and a couple of ridiculously long train wrecks of methods laid bare over on github), but this led me to my final lesson…

3) I know better…but I don’t know enough yet

I’ve been very fortunate that since I first started writing code I’ve been exposed to the “right” way of doing things from people like Jeff, our Code Academy mentors, the crew at 8th Light and the rest of the Chicago community. During the past six weeks at 8th Light I’ve also been reading a lot of theory and surrounded daily by crews working within the strict principles that the company adheres to. However, there’s definitely been times over the past couple of weeks that my knowledge of that theory and principles has prevented me from writing code that can at least “get the job done”. For example, I’ll start to write out a solution, but by the time I start writing my second line I realize that it’s going to be a pretty ugly method so I start over… and then the cycle repeats and repeats until I feel like I’m just banging my head against a wall in the hopes that the wall gives before my head does.

But therein lies the lesson, and part of what I’ve learned with the N-queens problem: I’m going to need to write some ugly solutions before I can really start to learn and apply the theories and principles necessary to make it better. Russ Olsen has a great quote in Eloquent Ruby that “writing clear code is a battle of inches”, and it certainly feels like a battle- but every inch also feels like a victory. I’m also reminded of Ira Glass’s advice for beginners: “but your taste, the thing that got you into the game, is still killer. And your taste is why your work disappoints you.” I don’t know if I would go as far as to say that I have killer taste in code, but I’ve definitely felt some frustration, and I’m most certainly a beginner.