Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
  • 10 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on Dec 07, 2011
@steveklabnik Adding dotfiles.
I often like to start out a project with a .gitignore and a .rvmrc.
Documenting which Ruby you're using is a good start, and I hate
accidentally adding vim's swapfiles into my repos.
@steveklabnik Requesting XML with Net::HTTP.
First off, I wanted to figure out how the hell to use Net::HTTP. It
never fails, I always forget. I did a google search for 'request
headers net::http ruby' and came up with the documentation, which had
an example I modified to get this.

If you run it, you can see the initial maze XML come back. Awesome.
@steveklabnik Wrapping up Net::HTTP.
Now that I have that working, I want to make a method that I can use. I
take these steps really slow, _especially_ since I'm being bad and
doing this without tests. It's just exploratory programming...

Everyone says that in their first few commits, anyway.
@steveklabnik Fetch start of maze.
First thing we need to do is grab the @start link. We'll use nokogiri
to parse that out. Pretty simple.
@steveklabnik Wrap up that href extraction.
My Ruby style tends to be of the 'zillions of tiny methods' variety. So
I wrap up _everything_ as methods, even if I'll only use them once, for
clarity. This time I did two at once, because I'm impatient and one of
them is only two lines. I got lucky...

Developing software is all about discipline. You don't _have_ to follow
best practices, but it's always those times that come back to bite you
in the end.
@steveklabnik Extracting directions.
Since these are the exact same, I did them all at the same time too.

Now we print out which directions we can go in in the current room. You
gotta hit control-c to break out, and you don't go anywhere. Whatever.
@steveklabnik Accepting input for the game.
Doing this kind of dispatch feels ugly, but since the end goal is
automated maze solving, I'm doing it anyway.

Also, exit revealed something quite interesting. Can't name a variable
'exit', or else it quits Ruby. hahahaha!

Oh, and you can't actually exit yet. Guess what I'm doing next...
@steveklabnik Leaving!
This time, since it really goes inside that loop, I built it as a
method from the beginning. Most of the implementation is the same as
extract_href_from_xml. Sweet.
@steveklabnik Adding winning message.
What kind of game doesn't congratulate you when you win?
@steveklabnik Implement automated solver.
We go from an 'choose your own adventure' style to an automatic

And let's make some comments, show them an example of what we're
doing and why. Always like to link to the definition of the type I'm
working with, makes it a lot easier.
Showing with 70 additions and 1 deletion.
  1. +2 −0 .gitignore
  2. +1 −0 .rvmrc
  3. +0 −1
  4. +67 −0 maze.rb
2 .gitignore
@@ -0,0 +1,2 @@
1 .rvmrc
@@ -0,0 +1 @@
+rvm use 1.9.3
@@ -1,4 +1,3 @@
Some experiments with maze+xml.
You're gonna need to 'gem install nokogiri' to get this going.
67 maze.rb
@@ -0,0 +1,67 @@
+# This code solves one of Mike Amundsen's maze+xml mazes:
+# The code isn't great. I just wanted to see how easy it'd be. So I built up a little test, extracted
+# some stuff into a method... next thing you know I've got a little procedural application.
+# Backtracking implementation borrowed from because I'm lazy.
+require 'uri'
+require 'net/http'
+require 'nokogiri'
+def request_xml(url)
+ uri = URI(url)
+ req =
+ req['Accept'] = "application/xml"
+ res = Net::HTTP.start(uri.hostname, uri.port) {|http|
+ http.request(req)
+ }
+ res.body
+def xml_has_completed?(xml)
+ Nokogiri::XML(xml).xpath("//completed").first
+def extract_href_from_xml(rel, xml)
+ doc = Nokogiri::XML(xml)
+ node = doc.xpath("//link[@rel=\"#{rel}\"]").first
+ return nil unless node
+ node[:href] #uuuuuuuuugh can't use Hash#fetch because it's not a hash.
+def start_uri
+ xml = request_xml('')
+ extract_href_from_xml('start', xml)
+xml = request_xml(start_uri)
+visited = {}
+path = []
+steps = 0
+ link = ["start", "east", "west", "south", "north", "exit"].collect do |direction|
+ extract_href_from_xml(direction, xml)
+ end.find {|href| href && !visited[href] }
+ if !link
+ path.pop
+ link = path.pop
+ end
+ visited[link] = true
+ path << link
+ xml = request_xml(link)
+ steps = steps + 1
+puts "you win in #{steps}!"

No commit comments for this range

Something went wrong with that request. Please try again.