Skip to content

Instantly share code, notes, and snippets.

@nono
Created April 13, 2011 21:02
Show Gist options
  • Select an option

  • Save nono/918410 to your computer and use it in GitHub Desktop.

Select an option

Save nono/918410 to your computer and use it in GitHub Desktop.
bin/maze.rb
#!/usr/bin/env ruby
require "maze"
i = 1
e = nil
loop do
maze = Maze.new(i, e)
maze.fetch
maze.construct
maze.solve
maze.respond
$stderr.puts ">>> #{maze.id}: #{maze.success} <<<"
exit if !maze.success
File.open("tmp/solution_#{maze.id}", "w+") { |f| f << maze.solution }
e = maze.expiry
i += 1
end
require 'yajl'
class Maze
attr_accessor :data, :id, :expiry, :success, :in, :out, :solution
KEY = "vCYVFJtCSDgbLttdrPcfdA%3D%3D"
def initialize(id, expiry=nil)
@id = id
@expiry = expiry
end
def fetch
e = expiry ? "&expiry=#{@expiry}" : ""
out = `curl http://beta.agilecup.org/problem/#{"%02d" % @id}?key=#{KEY}#{e}`
File.open("tmp/problem_#{@id}", "w+") { |f| f << out }
@data = Yajl::Parser.parse(out)
end
def respond
e = expiry ? "&expiry=#{@expiry}" : ""
out = `curl -X POST -d "key=#{KEY}&solution=#{@solution}#{e}" http://beta.agilecup.org/solution/#{"%02d" % @id}`
File.open("tmp/out_#{@id}", "w+") { |f| f << out }
d = Yajl::Parser.parse(out)
@success = d["success"] == "ok"
@expiry = d["expiry"]
end
def construct
@rows = @data.split("\n")
# Find in and out
@rows.each.with_index do |row, y|
x = row.index("I")
@in = [x, y] if x
end
end
def north(x, y)
[x, y-1]
end
def west(x, y)
[x-1, y]
end
def east(x, y)
[x+1, y]
end
def south(x, y)
[x, y+1]
end
def can_move_to?(x, y)
y >= 0 && y < nb_rows &&
x >= 0 && x < nb_columns &&
square(x, y) != "#"
end
def square(x, y)
@rows[y][x]
end
def nb_rows
@rows.length
end
def nb_columns
@rows.first.length
end
def moves
{
:east => "E",
:west => "W",
:north => "N",
:south => "S"
}
end
def solve
current = { @in => "" }
visited = {}
@data.length.times do
after = {}
current.each do |pos, sequence|
moves.each do |sym, letter|
x, y = send(sym, *pos)
next if visited.keys.include? [x,y]
if can_move_to?(x, y)
if square(x, y) == "O"
@solution = sequence + letter
return
else
after[ [x,y] ] = sequence + letter
end
end
end
end
current = after
end
@solution = "I"
end
end
#!/usr/bin/env ruby
require "minitest/autorun"
require "maze"
describe Maze do
before do
@maze = Maze.new(1)
data = File.read("tmp/problem_1")
@maze.data = Yajl::Parser.parse(data)
@maze.construct
end
it "find in and out" do
@maze.in.must_equal [1, 0]
end
it "fetches a square" do
@maze.square(0,0).must_equal "#"
@maze.square(0,1).must_equal "#"
@maze.square(1,0).must_equal "I"
@maze.square(1,1).must_equal "O"
end
it "counts rows and columns" do
@maze.nb_rows.must_equal 2
@maze.nb_columns.must_equal 3
end
it "calculates the next square of a given position" do
@maze.north(0, 1).must_equal [0, 0]
@maze.south(0, 1).must_equal [0, 2]
@maze.east(0, 1).must_equal [1, 1]
@maze.west(0, 1).must_equal [-1, 1]
end
it "knows if we can move to a square" do
@maze.can_move_to?(1, 0).must_equal true
@maze.can_move_to?(1, 1).must_equal true
@maze.can_move_to?(2, 1).must_equal false
@maze.can_move_to?(0, 1).must_equal false
@maze.can_move_to?(2, 2).must_equal false
end
it "solve the first maze" do
@maze.solve
@maze.solution.must_equal "S"
end
it "solve the second maze" do
@maze = Maze.new(2)
data = File.read("tmp/problem_2")
@maze.data = Yajl::Parser.parse(data)
@maze.construct
@maze.solve
@maze.solution.must_equal "E"
end
it "solve the third maze" do
@maze = Maze.new(3)
data = File.read("tmp/problem_3")
@maze.data = Yajl::Parser.parse(data)
@maze.construct
@maze.solve
@maze.solution.must_equal "N"
end
end
@francois2metz
Copy link

Awesome :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment