Skip to content

Instantly share code, notes, and snippets.

@spaghetticode
Created March 31, 2012 18:00
Show Gist options
  • Save spaghetticode/2267162 to your computer and use it in GitHub Desktop.
Save spaghetticode/2267162 to your computer and use it in GitHub Desktop.
Mikamai Coding Contest: #3
class Maze
BREADCRUMBS = '.'
WALKABLE = ' '
WALL = 'X'
DEAD_END = 'D'
attr_reader :map, :coords
def initialize(map)
@map = map
@coords = to_a
end
def draw_path
coords.each_with_index do |row, y|
row.each_with_index do |icon, x|
@y, @x = y, x
walk
end
end
end
def to_a
rows.inject([]) do |board, row|
board << row.split(//).inject([]) {|arr, icon| arr << icon}
end
end
def to_s
coords.inject('') do |maze, row|
maze << "#{row.join}\n"
end.gsub(DEAD_END, ' ')
end
def walk
if current_position == WALKABLE
coords[@y][@x] = walkable? ? BREADCRUMBS : DEAD_END
end
end
def rows
@rows ||= map.split("\n")
end
def width
rows.first.size
end
def walkable?
nearby_coords.select do |position|
[WALL, DEAD_END].include? get(position)
end.size < 3
end
def current_position
get [@y, @x]
end
def get(coord)
coords[coord.first][coord.last]
end
def nearby_coords
[[@y-1, @x], [@y+1, @x], [@y, @x-1], [@y, @x+1]]
end
end
require 'rspec'
map = <<-MAZE
XXXXXXXXXXXX
# XXX X o
XXX X X X XX
XX XX
XXXXXXXXXXXX
MAZE
solution = <<-MAZE
XXXXXXXXXXXX
#...XXX X..o
XXX.X X X.XX
XX .......XX
XXXXXXXXXXXX
MAZE
describe Maze do
subject { Maze.new(map) }
it 'assings map' do
subject.map.should == map
end
describe '#rows' do
it 'splits map in rows' do
subject.rows.size.should == 5
end
end
describe '#width' do
it 'returns the map width' do
subject.width.should == 12
end
end
describe '#to_a' do
it 'returns bidimensional array' do
subject.to_a.should be_an(Array)
subject.to_a.first.should be_an(Array)
end
end
describe '#to_s' do
it 'returns a string' do
subject.to_s.should be_a(String)
end
context 'when path has not been walked yet' do
it 'returns original map' do
subject.to_s.should == map
end
end
end
describe '#coords' do
it 'returns the maze in array format' do
subject.coords.should == subject.to_a
end
end
describe '#get' do
it 'wraps array access to coords' do
subject.get([1,2]).should == subject.coords[1][2]
end
end
describe '#current_position' do
it 'should return the icon in the current position' do
subject.instance_eval { @x, @y = 11, 1 }
subject.current_position.should == 'o'
end
end
describe '#nearby_coords' do
it 'returns an array of coordinates' do
subject.instance_eval { @x, @y = 2, 1}
subject.nearby_coords.should =~ [[0, 2], [2, 2], [1, 1], [1,3]]
end
end
describe '#walkable?' do
context 'when the coord is surrounded by 3 or more walls/dead ends' do
it 'is false' do
subject.instance_eval {@x, @y = 2, 3}
subject.should_not be_walkable
end
end
context 'when the coord is surrounded by less than 3 walls/dead ends' do
it 'is true' do
subject.instance_eval {@x, @y = 1, 1}
subject.should be_walkable
end
end
end
describe '#walk' do
context 'when the coord is walkable' do
it 'should change it to breadcrumbs icon' do
subject.instance_eval { @x, @y = 1, 1 }
subject.walk
subject.get([1, 1]).should == '.'
end
end
end
describe '#draw_path' do
it 'should draw the path to exit' do
subject.draw_path
subject.to_s.should == solution
end
end
end
puts Maze.new(map).tap {|bc| bc.draw_path}.to_s
require 'benchmark'
Benchmark.bm do |bm|
bm.report 'Andrea Longhi' do
10000.times { Maze.new(map).draw_path }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment